Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # If you have any idea of what is going wrong, please email me to florian <dot> florensa <at> gmail <dot> com
- #include <sys/cdefs.h>
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/endian.h>
- #include <sys/lock.h>
- #include <sys/kernel.h>
- #include <sys/queue.h>
- #include <sys/queue.h>
- #include <sys/malloc.h>
- #include <sys/taskqueue.h>
- #include <sys/mutex.h>
- #include <sys/condvar.h>
- #include <sys/proc.h>
- #include <machine/bus.h>
- #include <machine/cpu.h>
- #include <machine/stdarg.h>
- #include <cam/cam.h>
- #include <cam/cam_debug.h>
- #include <cam/cam_ccb.h>
- #include <cam/cam_sim.h>
- #include <cam/cam_xpt.h>
- #include <cam/cam_xpt_sim.h>
- #include <cam/cam_debug.h>
- #include <cam/scsi/scsi_all.h>
- #include <cam/scsi/scsi_message.h>
- #include <sys/unistd.h>
- #include <sys/kthread.h>
- #include <sys/conf.h>
- #include <sys/module.h>
- #include <sys/ioccom.h>
- #include <sys/devicestat.h>
- #include <cam/cam_periph.h>
- #include <cam/cam_xpt_periph.h>
- #include "platform.h"
- #include "freebsd.h"
- #include "os.h"
- #define vhba_SIMQ_SIZE 255
- static void vhba_cam_done(vhba_scsi_cmd_t *scsi_cmd)
- {
- union ccb *ccb;
- struct vhba_cmd *cmd;
- cmd = (struct vhba_cmd *)scsi_cmd->private;
- ccb = cmd->ccb;
- ccb->ccb_h.status = CAM_REQ_CMP;
- os_free(cmd); //free wrapper
- xpt_done(ccb);
- }
- static void vhba_cam_action(struct cam_sim *sim, union ccb *ccb)
- {
- struct ccb_trans_settings *cts;
- struct vhba_softc *vhba_softc;
- struct ccb_scsiio *csio = &ccb->csio;
- vhba_device_t *scsi_dev;
- vhba_scsi_cmd_t *scsi_cmd;
- struct vhba_cmd *cmd;
- vhba_softc = cam_sim_softc(sim);
- scsi_dev = vhba_softc->scsi_dev;
- if (scsi_dev == NULL) {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
- return;
- }
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- ccb->ccb_h.status &= ~CAM_STATUS_MASK;
- ccb->ccb_h.status |= CAM_REQ_INPROG;
- cmd = os_alloc(sizeof(struct vhba_cmd)); //malloc wrapper
- if (cmd == NULL) {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- break;
- }
- cmd->vhba_softc = vhba_softc;
- cmd->fini = 0;
- cmd->ccb = ccb;
- scsi_cmd = &cmd->scsi_cmd;
- scsi_cmd->addr = vhba_softc->scsi_dev->asd_addr;
- scsi_cmd->private = cmd;
- scsi_cmd->comp_func = vhba_cam_done;
- scsi_cmd->timeout = ccb->ccb_h.timeout;
- //Copy only the header of the scsi_cmd, and get needed information later
- if (csio->ccb_h.flags & CAM_CDB_POINTER)
- memcpy(&scsi_cmd->scsi_cmd_buf, csio->cdb_io.cdb_ptr, MIN(csio->dxfer_len, 16));
- else
- memcpy(&scsi_cmd->scsi_cmd_buf, &csio->cdb_io.cdb_bytes, MIN(csio->dxfer_len, 16));
- if (vhba_scsi_start(scsi_cmd) < 0) { //vhba_scsi_start processes the command, copy back the result and call the comp_func
- os_free(cmd); //free wrapper
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- break;
- }
- return;
- case XPT_RESET_DEV:
- ccb->ccb_h.status = CAM_REQ_CMP;
- break;
- case XPT_GET_TRAN_SETTINGS:
- cts = &ccb->cts;
- cts->protocol_version = SCSI_REV_SPC3;
- cts->protocol = PROTO_SCSI;
- cts->transport_version = 0;
- cts->transport = XPORT_PPB;
- ccb->ccb_h.status = CAM_REQ_CMP;
- break;
- case XPT_CALC_GEOMETRY:
- cam_calc_geometry(&ccb->ccg, 1);
- break;
- case XPT_RESET_BUS: /* Reset the specified bus */
- ccb->ccb_h.status = CAM_REQ_CMP;
- break;
- case XPT_PATH_INQ: /* Path routing inquiry */
- {
- struct ccb_pathinq *cpi = &ccb->cpi;
- cpi->version_num = 1;
- cpi->max_target = 63;
- cpi->max_lun = 16383;
- cpi->hba_misc = PIM_NOBUSRESET;
- cpi->initiator_id = cpi->max_target + 1;
- cpi->transport = XPORT_PPB;
- cpi->base_transfer_speed = 1000000;
- cpi->protocol = PROTO_SCSI;
- cpi->protocol_version = SCSI_REV_SPC3;
- strlcpy(cpi->sim_vid, "vhba_sim", SIM_IDLEN);
- strlcpy(cpi->hba_vid, "vhba_hba", HBA_IDLEN);
- strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
- cpi->unit_number = cam_sim_unit(sim);
- cpi->ccb_h.status = CAM_REQ_CMP;
- break;
- }
- default:
- ccb->ccb_h.status = CAM_REQ_INVALID;
- break;
- }
- xpt_done(ccb);
- }
- static void vhba_cam_poll(struct cam_sim *sim)
- {
- //FIXME ?
- (void)sim;
- }
- void vhba_cam_fini(struct vhba_softc *vhba_softc)
- {
- xpt_free_path(vhba_softc->path);
- xpt_bus_deregister(cam_sim_path(vhba_softc->sim));
- cam_sim_free(vhba_softc->sim, TRUE);
- os_free(vhba_softc);
- }
- struct vhba_softc *vhba_cam_init(target_id_t target_id, lun_id_t lun_id)
- {
- struct vhba_softc *vhba_softc = NULL;
- struct cam_devq *devq = NULL;
- devq = cam_simq_alloc(vhba_SIMQ_SIZE);
- if (devq == NULL)
- goto err;
- vhba_softc = os_alloc(sizeof(struct vhba_softc));
- if (vhba_softc == NULL)
- goto err;
- (void)snprintf(&vhba_softc->name[0], 16, "vhba_t%dl%lu", target_id, lun_id);
- mtx_init(&vhba_softc->cam_mtx, "vhba-cam", NULL, MTX_DEF);
- vhba_softc->sim = cam_sim_alloc(vhba_cam_action, vhba_cam_poll, vhba_softc->name, vhba_softc, 0, &vhba_softc->cam_mtx, vhba_MAX_CMDS, vhba_MAX_CMDS, devq);
- if (vhba_softc->sim == NULL)
- goto err;
- if (xpt_bus_register(vhba_softc->sim, *(device_t *)vhba_softc, 0) != CAM_SUCCESS)
- goto err;
- if (xpt_create_path(&vhba_softc->path, NULL, cam_sim_path(vhba_softc->sim), target_id, lun_id) != CAM_REQ_CMP)
- goto pathfailed;
- return vhba_softc;
- pathfailed:
- xpt_bus_deregister(cam_sim_path(vhba_softc->sim));
- err:
- if (vhba_softc && vhba_softc->sim) {
- cam_sim_free(vhba_softc->sim, TRUE);
- os_free(vhba_softc);
- } else if (vhba_softc) {
- cam_simq_free(devq);
- os_free(vhba_softc);
- } else if (devq)
- cam_simq_free(devq);
- return NULL;
- }
- void
- online_device(void *v)
- {
- vhba_device_t *scsi_dev;
- struct vhba_softc *vhba_softc;
- union ccb *done_ccb;
- scsi_dev = (vhba_device_t *) v;
- vhba_softc = vhba_cam_init(SCSI2TGT(scsi_dev->addr), SCSI2LUN(scsi_dev->addr));
- if (vhba_softc == NULL)
- return ;
- scsi_dev->softc = vhba_softc;
- done_ccb = xpt_alloc_ccb_nowait();
- xpt_setup_ccb(&done_ccb->ccb_h, vhba_softc->path, CAM_PRIORITY_NORMAL);
- done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action(done_ccb);
- xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb);
- }
- void
- offline_device(void *v)
- {
- vhba_device_t *scsi_dev;
- struct vhba_softc *vhba_softc;
- scsi_dev = (vhba_device_t *) v;
- vhba_softc = (struct vhba_softc *) scsi_dev->softc;
- if (vhba_softc == NULL)
- return ;
- xpt_async(AC_LOST_DEVICE, vhba_softc->path, NULL);
- vhba_cam_fini(vhba_softc);
- asi_free_scsi_dev(scsi_dev);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement