static void * nvme_sim_new_controller(struct nvme_controller *ctrlr) { struct cam_devq *devq; int max_trans; int unit; struct nvme_sim_softc *sc = NULL; max_trans = 256;/* XXX not so simple -- must match queues */ unit = device_get_unit(ctrlr->dev); devq = cam_simq_alloc(max_trans); if (devq == NULL) return NULL; sc = malloc(sizeof(*sc), M_NVME, M_ZERO | M_WAITOK); sc->s_ctrlr = ctrlr; sc->s_sim = cam_sim_alloc(nvme_sim_action, nvme_sim_poll, "nvme", sc, unit, &ctrlr->lock, max_trans, max_trans, devq); if (sc->s_sim == NULL) { printf("Failed to allocate a sim\n"); cam_simq_free(devq); free(sc, M_NVME); return NULL; } return sc; }
int ic_init(isc_session_t *sp) { struct cam_sim *sim; struct cam_devq *devq; debug_called(8); if((devq = cam_simq_alloc(256)) == NULL) return ENOMEM; #if __FreeBSD_version >= 700000 mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF); #else isp->cam_mtx = Giant; #endif sim = cam_sim_alloc(ic_action, ic_poll, "iscsi", sp, sp->sid, // unit #if __FreeBSD_version >= 700000 &sp->cam_mtx, #endif 1, // max_dev_transactions 0, // max_tagged_dev_transactions devq); if(sim == NULL) { cam_simq_free(devq); #if __FreeBSD_version >= 700000 mtx_destroy(&sp->cam_mtx); #endif return ENXIO; } CAM_LOCK(sp); if(xpt_bus_register(sim, #if __FreeBSD_version >= 700000 NULL, #endif 0/*bus_number*/) != CAM_SUCCESS) { cam_sim_free(sim, /*free_devq*/TRUE); CAM_UNLOCK(sp); #if __FreeBSD_version >= 700000 mtx_destroy(&sp->cam_mtx); #endif return ENXIO; } sp->cam_sim = sim; CAM_UNLOCK(sp); sdebug(1, "cam subsystem initialized"); ic_scan(sp); return 0; }
int ahci_cam_attach(struct ahci_port *ap) { struct cam_devq *devq; struct cam_sim *sim; int error; int unit; /* * We want at least one ccb to be available for error processing * so don't let CAM use more then ncmds - 1. */ unit = device_get_unit(ap->ap_sc->sc_dev); if (ap->ap_sc->sc_ncmds > 1) devq = cam_simq_alloc(ap->ap_sc->sc_ncmds - 1); else devq = cam_simq_alloc(ap->ap_sc->sc_ncmds); if (devq == NULL) { return (ENOMEM); } /* * Give the devq enough room to run with 32 max_dev_transactions, * but set the overall max tags to 1 until NCQ is negotiated. */ sim = cam_sim_alloc(ahci_xpt_action, ahci_xpt_poll, "ahci", (void *)ap, unit, &ap->ap_sim_lock, 32, 1, devq); cam_simq_release(devq); if (sim == NULL) { return (ENOMEM); } ap->ap_sim = sim; ahci_os_unlock_port(ap); lockmgr(&ap->ap_sim_lock, LK_EXCLUSIVE); error = xpt_bus_register(ap->ap_sim, ap->ap_num); lockmgr(&ap->ap_sim_lock, LK_RELEASE); ahci_os_lock_port(ap); if (error != CAM_SUCCESS) { ahci_cam_detach(ap); return (EINVAL); } ap->ap_flags |= AP_F_BUS_REGISTERED; if (ap->ap_probe == ATA_PROBE_NEED_IDENT) error = ahci_cam_probe(ap, NULL); else error = 0; if (error) { ahci_cam_detach(ap); return (EIO); } ap->ap_flags |= AP_F_CAM_ATTACHED; return(0); }
/******************************************************************************** * Attach our 'real' SCSI channels to CAM */ static int amr_cam_attach(device_t dev) { struct amr_softc *sc; struct cam_devq *devq; int chn, error; sc = device_get_softc(dev); /* initialise the ccb queue */ TAILQ_INIT(&sc->amr_cam_ccbq); /* * Allocate a devq for all our channels combined. This should * allow for the maximum number of SCSI commands we will accept * at one time. Save the pointer in the softc so we can find it later * during detach. */ if ((devq = cam_simq_alloc(AMR_MAX_SCSI_CMDS)) == NULL) return(ENOMEM); sc->amr_cam_devq = devq; /* * Iterate over our channels, registering them with CAM */ for (chn = 0; chn < sc->amr_maxchan; chn++) { /* allocate a sim */ if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action, amr_cam_poll, "amr", sc, device_get_unit(sc->amr_dev), &sc->amr_list_lock, 1, AMR_MAX_SCSI_CMDS, devq)) == NULL) { cam_simq_free(devq); device_printf(sc->amr_dev, "CAM SIM attach failed\n"); return(ENOMEM); } /* register the bus ID so we can get it later */ mtx_lock(&sc->amr_list_lock); error = xpt_bus_register(sc->amr_cam_sim[chn], sc->amr_dev,chn); mtx_unlock(&sc->amr_list_lock); if (error) { device_printf(sc->amr_dev, "CAM XPT bus registration failed\n"); return(ENXIO); } } /* * XXX we should scan the config and work out which devices are * actually protected. */ sc->amr_cam_command = amr_cam_command; return(0); }
/******************************************************************************** * Attach the real and virtual SCSI busses to CAM */ int mly_cam_attach(struct mly_softc *sc) { struct cam_devq *devq; int chn, nchn; debug_called(1); /* initialise the CCB queue */ TAILQ_INIT(&sc->mly_cam_ccbq); /* * Allocate a devq for all our channels combined. */ if ((devq = cam_simq_alloc(sc->mly_controllerinfo->maximum_parallel_commands)) == NULL) { mly_printf(sc, "can't allocate CAM SIM\n"); return(ENOMEM); } /* * Iterate over channels, registering them with CAM. */ nchn = sc->mly_controllerinfo->physical_channels_present + sc->mly_controllerinfo->virtual_channels_present; for (chn = 0; chn < nchn; chn++) { /* allocate a sim */ if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc, device_get_unit(sc->mly_dev), 1, sc->mly_controllerinfo->maximum_parallel_commands, devq)) == NULL) { cam_simq_free(devq); mly_printf(sc, "CAM SIM attach failed\n"); return(ENOMEM); } /* register the bus ID so we can get it later */ if (xpt_bus_register(sc->mly_cam_sim[chn], chn)) { mly_printf(sc, "CAM XPT bus registration failed\n"); return(ENXIO); } debug(1, "registered sim %p bus %d", sc->mly_cam_sim[chn], chn); } return(0); }
/* * vpo_attach() */ static int vpo_attach(device_t dev) { struct vpo_data *vpo = DEVTOSOFTC(dev); struct cam_devq *devq; int error; /* low level attachment */ if (vpo->vpo_isplus) { if ((error = imm_attach(&vpo->vpo_io))) return (error); } else { if ((error = vpoio_attach(&vpo->vpo_io))) return (error); } /* ** Now tell the generic SCSI layer ** about our bus. */ devq = cam_simq_alloc(/*maxopenings*/1); /* XXX What about low-level detach on error? */ if (devq == NULL) return (ENXIO); vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, device_get_unit(dev), /*untagged*/1, /*tagged*/0, devq); if (vpo->sim == NULL) { cam_simq_free(devq); return (ENXIO); } if (xpt_bus_register(vpo->sim, /*bus*/0) != CAM_SUCCESS) { cam_sim_free(vpo->sim, /*free_devq*/TRUE); return (ENXIO); } if (xpt_create_path(&vpo->path, /*periph*/NULL, cam_sim_path(vpo->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(vpo->sim)); cam_sim_free(vpo->sim, /*free_devq*/TRUE); return (ENXIO); } /* all went ok */ return (0); }
void mpt_cam_attach(mpt_softc_t *mpt) { struct cam_devq *devq; struct cam_sim *sim; int maxq; mpt->bus = 0; maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))? mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt); /* * Create the device queue for our SIM(s). */ devq = cam_simq_alloc(maxq); if (devq == NULL) { return; } /* * Construct our SIM entry. */ sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt, mpt->unit, 1, maxq, devq); if (sim == NULL) { cam_simq_free(devq); return; } /* * Register exactly the bus. */ if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { cam_sim_free(sim, TRUE); return; } if (xpt_create_path(&mpt->path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); return; } mpt->sim = sim; }
/* * Register the driver as a CAM SIM */ static int aac_cam_attach(device_t dev) { struct cam_devq *devq; struct cam_sim *sim; struct cam_path *path; struct aac_cam *camsc; struct aac_sim *inf; fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); camsc = (struct aac_cam *)device_get_softc(dev); inf = (struct aac_sim *)device_get_ivars(dev); camsc->inf = inf; devq = cam_simq_alloc(inf->TargetsPerBus); if (devq == NULL) return (EIO); sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc, device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq); if (sim == NULL) { cam_simq_free(devq); return (EIO); } /* Since every bus has it's own sim, every bus 'appears' as bus 0 */ mtx_lock(&inf->aac_sc->aac_io_lock); if (xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) { cam_sim_free(sim, TRUE); mtx_unlock(&inf->aac_sc->aac_io_lock); return (EIO); } if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); mtx_unlock(&inf->aac_sc->aac_io_lock); return (EIO); } mtx_unlock(&inf->aac_sc->aac_io_lock); camsc->sim = sim; camsc->path = path; return (0); }
/******************************************************************************** * Attach our 'real' SCSI channels to CAM */ int amr_cam_attach(struct amr_softc *sc) { struct cam_devq *devq; int chn; /* initialise the ccb queue */ TAILQ_INIT(&sc->amr_cam_ccbq); /* * Allocate a devq for all our channels combined. This should * allow for the maximum number of SCSI commands we will accept * at one time. */ if ((devq = cam_simq_alloc(AMR_MAX_SCSI_CMDS)) == NULL) return(ENOMEM); /* * Iterate over our channels, registering them with CAM */ for (chn = 0; chn < sc->amr_maxchan; chn++) { /* allocate a sim */ if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action, amr_cam_poll, "amr", sc, device_get_unit(sc->amr_dev), 1, AMR_MAX_SCSI_CMDS, devq)) == NULL) { cam_simq_free(devq); device_printf(sc->amr_dev, "CAM SIM attach failed\n"); return(ENOMEM); } /* register the bus ID so we can get it later */ if (xpt_bus_register(sc->amr_cam_sim[chn], chn)) { device_printf(sc->amr_dev, "CAM XPT bus registration failed\n"); return(ENXIO); } } /* * XXX we should scan the config and work out which devices are actually * protected. */ return(0); }
int aha_attach(struct aha_softc *aha) { int tagged_dev_openings; struct cam_devq *devq; /* * We don't do tagged queueing, since the aha cards don't * support it. */ tagged_dev_openings = 0; /* * Create the device queue for our SIM. */ devq = cam_simq_alloc(aha->max_ccbs - 1); if (devq == NULL) return (ENOMEM); /* * Construct our SIM entry */ aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, device_get_unit(aha->dev), &aha->lock, 2, tagged_dev_openings, devq); if (aha->sim == NULL) { cam_simq_free(devq); return (ENOMEM); } mtx_lock(&aha->lock); if (xpt_bus_register(aha->sim, aha->dev, 0) != CAM_SUCCESS) { cam_sim_free(aha->sim, /*free_devq*/TRUE); mtx_unlock(&aha->lock); return (ENXIO); } if (xpt_create_path(&aha->path, /*periph*/NULL, cam_sim_path(aha->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(aha->sim)); cam_sim_free(aha->sim, /*free_devq*/TRUE); mtx_unlock(&aha->lock); return (ENXIO); } mtx_unlock(&aha->lock); return (0); }
/* * vpo_attach() */ static int vpo_attach(device_t dev) { struct vpo_data *vpo = DEVTOSOFTC(dev); device_t ppbus = device_get_parent(dev); struct ppb_data *ppb = device_get_softc(ppbus); /* XXX: layering */ struct cam_devq *devq; int error; /* low level attachment */ if (vpo->vpo_isplus) { if ((error = imm_attach(&vpo->vpo_io))) return (error); } else { if ((error = vpoio_attach(&vpo->vpo_io))) return (error); } /* ** Now tell the generic SCSI layer ** about our bus. */ devq = cam_simq_alloc(/*maxopenings*/1); /* XXX What about low-level detach on error? */ if (devq == NULL) return (ENXIO); vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, device_get_unit(dev), ppb->ppc_lock, /*untagged*/1, /*tagged*/0, devq); if (vpo->sim == NULL) { cam_simq_free(devq); return (ENXIO); } ppb_lock(ppbus); if (xpt_bus_register(vpo->sim, dev, /*bus*/0) != CAM_SUCCESS) { cam_sim_free(vpo->sim, /*free_devq*/TRUE); ppb_unlock(ppbus); return (ENXIO); } ppb_unlock(ppbus); return (0); }
/* * vpo_attach() */ static int vpo_attach(device_t dev) { struct vpo_data *vpo = DEVTOSOFTC(dev); struct cam_devq *devq; int error; /* low level attachment */ if (vpo->vpo_isplus) { if ((error = imm_attach(&vpo->vpo_io))) return (error); } else { if ((error = vpoio_attach(&vpo->vpo_io))) return (error); } /* ** Now tell the generic SCSI layer ** about our bus. */ devq = cam_simq_alloc(/*maxopenings*/1); /* XXX What about low-level detach on error? */ if (devq == NULL) return (ENXIO); vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, device_get_unit(dev), &sim_mplock, /*untagged*/1, /*tagged*/0, devq); cam_simq_release(devq); if (vpo->sim == NULL) { return (ENXIO); } if (xpt_bus_register(vpo->sim, /*bus*/0) != CAM_SUCCESS) { cam_sim_free(vpo->sim); return (ENXIO); } /* all went ok */ vpo_cam_rescan(vpo); /* have CAM rescan the bus */ return (0); }
static void * nvme_sim_new_controller(struct nvme_controller *ctrlr) { struct nvme_sim_softc *sc; struct cam_devq *devq; int max_trans; max_trans = ctrlr->max_hw_pend_io; devq = cam_simq_alloc(max_trans); if (devq == NULL) return (NULL); sc = malloc(sizeof(*sc), M_NVME, M_ZERO | M_WAITOK); sc->s_ctrlr = ctrlr; sc->s_sim = cam_sim_alloc(nvme_sim_action, nvme_sim_poll, "nvme", sc, device_get_unit(ctrlr->dev), &ctrlr->lock, max_trans, max_trans, devq); if (sc->s_sim == NULL) { printf("Failed to allocate a sim\n"); cam_simq_free(devq); goto err1; } if (xpt_bus_register(sc->s_sim, ctrlr->dev, 0) != CAM_SUCCESS) { printf("Failed to create a bus\n"); goto err2; } if (xpt_create_path(&sc->s_path, /*periph*/NULL, cam_sim_path(sc->s_sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { printf("Failed to create a path\n"); goto err3; } return (sc); err3: xpt_bus_deregister(cam_sim_path(sc->s_sim)); err2: cam_sim_free(sc->s_sim, /*free_devq*/TRUE); err1: free(sc, M_NVME); return (NULL); }
int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller) { struct isci_softc *isci = controller->isci; device_t parent = device_get_parent(isci->device); int unit = device_get_unit(isci->device); struct cam_devq *isci_devq = cam_simq_alloc(controller->sim_queue_depth); if(isci_devq == NULL) { isci_log_message(0, "ISCI", "isci_devq is NULL \n"); return (-1); } controller->sim = cam_sim_alloc(isci_action, isci_poll, "isci", controller, unit, &controller->lock, controller->sim_queue_depth, controller->sim_queue_depth, isci_devq); if(controller->sim == NULL) { isci_log_message(0, "ISCI", "cam_sim_alloc... fails\n"); cam_simq_free(isci_devq); return (-1); } if(xpt_bus_register(controller->sim, parent, controller->index) != CAM_SUCCESS) { isci_log_message(0, "ISCI", "xpt_bus_register...fails \n"); cam_sim_free(controller->sim, TRUE); mtx_unlock(&controller->lock); return (-1); } if(xpt_create_path(&controller->path, NULL, cam_sim_path(controller->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { isci_log_message(0, "ISCI", "xpt_create_path....fails\n"); xpt_bus_deregister(cam_sim_path(controller->sim)); cam_sim_free(controller->sim, TRUE); mtx_unlock(&controller->lock); return (-1); } return (0); }
static int mfip_attach(device_t dev) { struct mfip_softc *sc; struct mfi_softc *mfisc; sc = device_get_softc(dev); if (sc == NULL) return (EINVAL); mfisc = device_get_softc(device_get_parent(dev)); sc->dev = dev; sc->mfi_sc = mfisc; mfisc->mfi_cam_start = mfip_start; if ((sc->devq = cam_simq_alloc(MFI_SCSI_MAX_CMDS)) == NULL) return (ENOMEM); sc->sim = cam_sim_alloc(mfip_cam_action, mfip_cam_poll, "mfi", sc, device_get_unit(dev), &mfisc->mfi_io_lock, 1, MFI_SCSI_MAX_CMDS, sc->devq); if (sc->sim == NULL) { cam_simq_free(sc->devq); device_printf(dev, "CAM SIM attach failed\n"); return (EINVAL); } mtx_lock(&mfisc->mfi_io_lock); if (xpt_bus_register(sc->sim, dev, 0) != 0) { device_printf(dev, "XPT bus registration failed\n"); cam_sim_free(sc->sim, FALSE); cam_simq_free(sc->devq); mtx_unlock(&mfisc->mfi_io_lock); return (EINVAL); } mtx_unlock(&mfisc->mfi_io_lock); return (0); }
static int wds_attach(device_t dev) { struct wds *wp; struct cam_devq *devq; struct cam_sim *sim; struct cam_path *pathp; int i; int error = 0; wp = (struct wds *)device_get_softc(dev); wp->port_rid = 0; wp->port_r = bus_alloc_resource(dev, SYS_RES_IOPORT, &wp->port_rid, /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE); if (wp->port_r == NULL) return (ENXIO); /* We must now release resources on error. */ wp->drq_rid = 0; wp->drq_r = bus_alloc_resource(dev, SYS_RES_DRQ, &wp->drq_rid, /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE); if (wp->drq_r == NULL) goto bad; wp->intr_rid = 0; wp->intr_r = bus_alloc_resource(dev, SYS_RES_IRQ, &wp->intr_rid, /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE); if (wp->intr_r == NULL) goto bad; error = bus_setup_intr(dev, wp->intr_r, INTR_TYPE_CAM | INTR_ENTROPY, NULL, (driver_intr_t *)wds_intr, (void *)wp, &wp->intr_cookie); if (error) goto bad; /* now create the memory buffer */ error = bus_dma_tag_create(bus_get_dma_tag(dev), /*alignment*/4, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL, /*maxsize*/ sizeof(* wp->dx), /*nsegments*/ 1, /*maxsegsz*/ sizeof(* wp->dx), /*flags*/ 0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &wp->bustag); if (error) goto bad; error = bus_dmamem_alloc(wp->bustag, (void **)&wp->dx, /*flags*/ 0, &wp->busmap); if (error) goto bad; bus_dmamap_load(wp->bustag, wp->busmap, (void *)wp->dx, sizeof(* wp->dx), wds_alloc_callback, (void *)&wp->dx_p, /*flags*/0); /* initialize the wds_req structures on this unit */ for(i=0; i<MAXSIMUL; i++) { wp->dx->req[i].id = i; wp->wdsr_free |= 1<<i; } /* initialize the memory buffer allocation for this unit */ if (BUFSIZ / FRAGSIZ > 32) { fragsiz = (BUFSIZ / 32) & ~0x01; /* keep it word-aligned */ device_printf(dev, "data buffer fragment size too small. " "BUFSIZE / FRAGSIZE must be <= 32\n"); } else fragsiz = FRAGSIZ & ~0x01; /* keep it word-aligned */ wp->data_free = 0; nfrags = 0; for (i = fragsiz; i <= BUFSIZ; i += fragsiz) { nfrags++; wp->data_free = (wp->data_free << 1) | 1; } /* complete the hardware initialization */ if (wds_init(wp) != 0) goto bad; if (wds_getvers(wp) == -1) device_printf(dev, "getvers failed\n"); device_printf(dev, "using %d bytes / %d frags for dma buffer\n", BUFSIZ, nfrags); devq = cam_simq_alloc(MAXSIMUL); if (devq == NULL) goto bad; sim = cam_sim_alloc(wds_action, wds_poll, "wds", (void *) wp, wp->unit, &Giant, 1, 1, devq); if (sim == NULL) { cam_simq_free(devq); goto bad; } wp->sim = sim; if (xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) { cam_sim_free(sim, /* free_devq */ TRUE); goto bad; } if (xpt_create_path(&pathp, /* periph */ NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, /* free_devq */ TRUE); goto bad; } wp->path = pathp; return (0); bad: wds_free_resources(wp); if (error) return (error); else /* exact error is unknown */ return (ENXIO); }
void isp_attach(struct ispsoftc *isp) { int primary, secondary; struct ccb_setasync csa; struct cam_devq *devq; struct cam_sim *sim; struct cam_path *path; /* * Establish (in case of 12X0) which bus is the primary. */ primary = 0; secondary = 1; /* * Create the device queue for our SIM(s). */ devq = cam_simq_alloc(MAXISPREQUEST); if (devq == NULL) { return; } /* * Construct our SIM entry. */ sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, isp->isp_unit, 1, MAXISPREQUEST, devq); if (sim == NULL) { cam_simq_free(devq); return; } if (xpt_bus_register(sim, primary) != CAM_SUCCESS) { cam_sim_free(sim, TRUE); return; } if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); return; } xpt_setup_ccb(&csa.ccb_h, path, 5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_LOST_DEVICE; csa.callback = isp_cam_async; csa.callback_arg = sim; xpt_action((union ccb *)&csa); isp->isp_sim = sim; isp->isp_path = path; /* * If we have a second channel, construct SIM entry for that. */ if (IS_12X0(isp)) { sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, isp->isp_unit, 1, MAXISPREQUEST, devq); if (sim == NULL) { xpt_bus_deregister(cam_sim_path(isp->isp_sim)); xpt_free_path(isp->isp_path); cam_simq_free(devq); return; } if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) { xpt_bus_deregister(cam_sim_path(isp->isp_sim)); xpt_free_path(isp->isp_path); cam_sim_free(sim, TRUE); return; } if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(isp->isp_sim)); xpt_free_path(isp->isp_path); xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim, TRUE); return; } xpt_setup_ccb(&csa.ccb_h, path, 5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_LOST_DEVICE; csa.callback = isp_cam_async; csa.callback_arg = sim; xpt_action((union ccb *)&csa); isp->isp_sim2 = sim; isp->isp_path2 = path; } if (isp->isp_state == ISP_INITSTATE) isp->isp_state = ISP_RUNSTATE; }
/** * mrsas_cam_attach: Main entry to CAM subsystem * input: Adapter instance soft state * * This function is called from mrsas_attach() during initialization * to perform SIM allocations and XPT bus registration. If the kernel * version is 7.4 or earlier, it would also initiate a bus scan. */ int mrsas_cam_attach(struct mrsas_softc *sc) { struct cam_devq *devq; int mrsas_cam_depth; mrsas_cam_depth = sc->max_fw_cmds - MRSAS_INTERNAL_CMDS; if ((devq = cam_simq_alloc(mrsas_cam_depth)) == NULL) { device_printf(sc->mrsas_dev, "Cannot allocate SIM queue\n"); return(ENOMEM); } /* * Create SIM for bus 0 and register, also create path */ sc->sim_0 = cam_sim_alloc(mrsas_action, mrsas_poll, "mrsas", sc, device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth, mrsas_cam_depth, devq); if (sc->sim_0 == NULL){ device_printf(sc->mrsas_dev, "Cannot register SIM\n"); cam_simq_release(devq); return(ENXIO); } /* Initialize taskqueue for Event Handling */ TASK_INIT(&sc->ev_task, 0, (void *)mrsas_aen_handler, sc); sc->ev_tq = taskqueue_create("mrsas_taskq", M_NOWAIT | M_ZERO, taskqueue_thread_enqueue, &sc->ev_tq); /* Run the task queue with lowest priority */ taskqueue_start_threads(&sc->ev_tq, 1, 255, -1, "%s taskq", device_get_nameunit(sc->mrsas_dev)); lockmgr(&sc->sim_lock, LK_EXCLUSIVE); if (xpt_bus_register(sc->sim_0, 0) != CAM_SUCCESS) { cam_sim_free(sc->sim_0); cam_simq_release(devq); lockmgr(&sc->sim_lock, LK_RELEASE); return(ENXIO); } if (xpt_create_path(&sc->path_0, NULL, cam_sim_path(sc->sim_0), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sc->sim_0)); cam_sim_free(sc->sim_0); cam_simq_release(devq); lockmgr(&sc->sim_lock, LK_RELEASE); return(ENXIO); } lockmgr(&sc->sim_lock, LK_RELEASE); /* * Create SIM for bus 1 and register, also create path */ sc->sim_1 = cam_sim_alloc(mrsas_action, mrsas_poll, "mrsas", sc, device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth, mrsas_cam_depth, devq); cam_simq_release(devq); if (sc->sim_1 == NULL){ device_printf(sc->mrsas_dev, "Cannot register SIM\n"); return(ENXIO); } lockmgr(&sc->sim_lock, LK_EXCLUSIVE); if (xpt_bus_register(sc->sim_1, 1) != CAM_SUCCESS){ cam_sim_free(sc->sim_1); lockmgr(&sc->sim_lock, LK_RELEASE); return(ENXIO); } if (xpt_create_path(&sc->path_1, NULL, cam_sim_path(sc->sim_1), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sc->sim_1)); cam_sim_free(sc->sim_1); lockmgr(&sc->sim_lock, LK_RELEASE); return(ENXIO); } lockmgr(&sc->sim_lock, LK_RELEASE); #if (__FreeBSD_version <= 704000) if (mrsas_bus_scan(sc)){ device_printf(sc->mrsas_dev, "Error in bus scan.\n"); return(1); } #endif return(0); }
int cfcs_init(void) { struct cfcs_softc *softc; struct ccb_setasync csa; struct ctl_port *port; int retval; softc = &cfcs_softc; bzero(softc, sizeof(*softc)); mtx_init(&softc->lock, "ctl2cam", NULL, MTX_DEF); port = &softc->port; port->frontend = &cfcs_frontend; port->port_type = CTL_PORT_INTERNAL; /* XXX KDM what should the real number be here? */ port->num_requested_ctl_io = 4096; snprintf(softc->port_name, sizeof(softc->port_name), "camsim"); port->port_name = softc->port_name; port->port_online = cfcs_online; port->port_offline = cfcs_offline; port->onoff_arg = softc; port->fe_datamove = cfcs_datamove; port->fe_done = cfcs_done; /* XXX KDM what should we report here? */ /* XXX These should probably be fetched from CTL. */ port->max_targets = 1; port->max_target_id = 15; port->targ_port = -1; retval = ctl_port_register(port); if (retval != 0) { printf("%s: ctl_port_register() failed with error %d!\n", __func__, retval); mtx_destroy(&softc->lock); return (retval); } /* * If the CTL frontend didn't tell us what our WWNN/WWPN is, go * ahead and set something random. */ if (port->wwnn == 0) { uint64_t random_bits; arc4rand(&random_bits, sizeof(random_bits), 0); softc->wwnn = (random_bits & 0x0000000fffffff00ULL) | /* Company ID */ 0x5000000000000000ULL | /* NL-Port */ 0x0300; softc->wwpn = softc->wwnn + port->targ_port + 1; ctl_port_set_wwns(port, true, softc->wwnn, true, softc->wwpn); } else { softc->wwnn = port->wwnn; softc->wwpn = port->wwpn; } mtx_lock(&softc->lock); softc->devq = cam_simq_alloc(port->num_requested_ctl_io); if (softc->devq == NULL) { printf("%s: error allocating devq\n", __func__); retval = ENOMEM; goto bailout; } softc->sim = cam_sim_alloc(cfcs_action, cfcs_poll, softc->port_name, softc, /*unit*/ 0, &softc->lock, 1, port->num_requested_ctl_io, softc->devq); if (softc->sim == NULL) { printf("%s: error allocating SIM\n", __func__); retval = ENOMEM; goto bailout; } if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) { printf("%s: error registering SIM\n", __func__); retval = ENOMEM; goto bailout; } if (xpt_create_path(&softc->path, /*periph*/NULL, cam_sim_path(softc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { printf("%s: error creating path\n", __func__); xpt_bus_deregister(cam_sim_path(softc->sim)); retval = EINVAL; goto bailout; } xpt_setup_ccb(&csa.ccb_h, softc->path, CAM_PRIORITY_NONE); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_LOST_DEVICE; csa.callback = cfcs_async; csa.callback_arg = softc->sim; xpt_action((union ccb *)&csa); mtx_unlock(&softc->lock); return (retval); bailout: if (softc->sim) cam_sim_free(softc->sim, /*free_devq*/ TRUE); else if (softc->devq) cam_simq_free(softc->devq); mtx_unlock(&softc->lock); mtx_destroy(&softc->lock); return (retval); }
int cfcs_init(void) { struct cfcs_softc *softc; struct ccb_setasync csa; struct ctl_frontend *fe; #ifdef NEEDTOPORT char wwnn[8]; #endif int retval; /* Don't continue if CTL is disabled */ if (ctl_disable != 0) return (0); softc = &cfcs_softc; retval = 0; bzero(softc, sizeof(*softc)); sprintf(softc->lock_desc, "ctl2cam"); mtx_init(&softc->lock, softc->lock_desc, NULL, MTX_DEF); fe = &softc->fe; fe->port_type = CTL_PORT_INTERNAL; /* XXX KDM what should the real number be here? */ fe->num_requested_ctl_io = 4096; snprintf(softc->port_name, sizeof(softc->port_name), "ctl2cam"); fe->port_name = softc->port_name; fe->port_online = cfcs_online; fe->port_offline = cfcs_offline; fe->onoff_arg = softc; fe->targ_enable = cfcs_targ_enable; fe->targ_disable = cfcs_targ_disable; fe->lun_enable = cfcs_lun_enable; fe->lun_disable = cfcs_lun_disable; fe->targ_lun_arg = softc; fe->fe_datamove = cfcs_datamove; fe->fe_done = cfcs_done; /* XXX KDM what should we report here? */ /* XXX These should probably be fetched from CTL. */ fe->max_targets = 1; fe->max_target_id = 15; retval = ctl_frontend_register(fe, /*master_SC*/ 1); if (retval != 0) { printf("%s: ctl_frontend_register() failed with error %d!\n", __func__, retval); mtx_destroy(&softc->lock); return (1); } /* * Get the WWNN out of the database, and create a WWPN as well. */ #ifdef NEEDTOPORT ddb_GetWWNN((char *)wwnn); softc->wwnn = be64dec(wwnn); softc->wwpn = softc->wwnn + (softc->fe.targ_port & 0xff); #endif /* * If the CTL frontend didn't tell us what our WWNN/WWPN is, go * ahead and set something random. */ if (fe->wwnn == 0) { uint64_t random_bits; arc4rand(&random_bits, sizeof(random_bits), 0); softc->wwnn = (random_bits & 0x0000000fffffff00ULL) | /* Company ID */ 0x5000000000000000ULL | /* NL-Port */ 0x0300; softc->wwpn = softc->wwnn + fe->targ_port + 1; fe->wwnn = softc->wwnn; fe->wwpn = softc->wwpn; } else { softc->wwnn = fe->wwnn; softc->wwpn = fe->wwpn; } mtx_lock(&softc->lock); softc->devq = cam_simq_alloc(fe->num_requested_ctl_io); if (softc->devq == NULL) { printf("%s: error allocating devq\n", __func__); retval = ENOMEM; goto bailout; } softc->sim = cam_sim_alloc(cfcs_action, cfcs_poll, softc->port_name, softc, /*unit*/ 0, &softc->lock, 1, fe->num_requested_ctl_io, softc->devq); if (softc->sim == NULL) { printf("%s: error allocating SIM\n", __func__); retval = ENOMEM; goto bailout; } if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) { printf("%s: error registering SIM\n", __func__); retval = ENOMEM; goto bailout; } if (xpt_create_path(&softc->path, /*periph*/NULL, cam_sim_path(softc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { printf("%s: error creating path\n", __func__); xpt_bus_deregister(cam_sim_path(softc->sim)); retval = 1; goto bailout; } xpt_setup_ccb(&csa.ccb_h, softc->path, CAM_PRIORITY_NONE); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_LOST_DEVICE; csa.callback = cfcs_async; csa.callback_arg = softc->sim; xpt_action((union ccb *)&csa); mtx_unlock(&softc->lock); return (retval); bailout: if (softc->sim) cam_sim_free(softc->sim, /*free_devq*/ TRUE); else if (softc->devq) cam_simq_free(softc->devq); mtx_unlock(&softc->lock); mtx_destroy(&softc->lock); return (retval); }
int tws_cam_attach(struct tws_softc *sc) { struct cam_devq *devq; int error; TWS_TRACE_DEBUG(sc, "entry", 0, sc); /* Create a device queue for sim */ /* * if the user sets cam depth to less than 1 * cam may get confused */ if ( tws_cam_depth < 1 ) tws_cam_depth = 1; if ( tws_cam_depth > (tws_queue_depth - TWS_RESERVED_REQS) ) tws_cam_depth = tws_queue_depth - TWS_RESERVED_REQS; TWS_TRACE_DEBUG(sc, "depths,ctlr,cam", tws_queue_depth, tws_cam_depth); if ((devq = cam_simq_alloc(tws_cam_depth)) == NULL) { tws_log(sc, CAM_SIMQ_ALLOC); return(ENOMEM); } /* * Create a SIM entry. Though we can support tws_cam_depth * simultaneous requests, we claim to be able to handle only * (tws_cam_depth), so that we always have reserved requests * packet available to service ioctls and internal commands. */ sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc, device_get_unit(sc->tws_dev), &sc->sim_lock, tws_cam_depth, 1, devq); /* 1, 1, devq); */ cam_simq_release(devq); if (sc->sim == NULL) { tws_log(sc, CAM_SIM_ALLOC); } /* Register the bus. */ lockmgr(&sc->sim_lock, LK_EXCLUSIVE); if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) { cam_sim_free(sc->sim); sc->sim = NULL; /* so cam_detach will not try to free it */ lockmgr(&sc->sim_lock, LK_RELEASE); tws_log(sc, TWS_XPT_BUS_REGISTER); return(ENXIO); } if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sc->sim)); cam_sim_free(sc->sim); tws_log(sc, TWS_XPT_CREATE_PATH); lockmgr(&sc->sim_lock, LK_RELEASE); return(ENXIO); } if ((error = tws_bus_scan(sc))) { tws_log(sc, TWS_BUS_SCAN_REQ); lockmgr(&sc->sim_lock, LK_RELEASE); return(error); } lockmgr(&sc->sim_lock, LK_RELEASE); return(0); }
/* * Function name: tw_osli_cam_attach * Description: Attaches the driver to CAM. * * Input: sc -- ptr to OSL internal ctlr context * Output: None * Return value: 0 -- success * non-zero-- failure */ TW_INT32 tw_osli_cam_attach(struct twa_softc *sc) { struct cam_devq *devq; tw_osli_dbg_dprintf(3, sc, "entered"); /* * Create the device queue for our SIM. */ if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2100, "Failed to create SIM device queue", ENOMEM); return(ENOMEM); } /* * Create a SIM entry. Though we can support TW_OSLI_MAX_NUM_REQUESTS * simultaneous requests, we claim to be able to handle only * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request * packet available to service ioctls and AENs. */ tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc"); sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc, device_get_unit(sc->bus_dev), sc->sim_lock, TW_OSLI_MAX_NUM_IOS, 1, devq); if (sc->sim == NULL) { cam_simq_free(devq); tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2101, "Failed to create a SIM entry", ENOMEM); return(ENOMEM); } /* * Register the bus. */ tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register"); mtx_lock(sc->sim_lock); if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) { cam_sim_free(sc->sim, TRUE); sc->sim = NULL; /* so cam_detach will not try to free it */ tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2102, "Failed to register the bus", ENXIO); mtx_unlock(sc->sim_lock); return(ENXIO); } tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path"); if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path (sc->sim)); /* Passing TRUE to cam_sim_free will free the devq as well. */ cam_sim_free(sc->sim, TRUE); tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2103, "Failed to create path", ENXIO); mtx_unlock(sc->sim_lock); return(ENXIO); } mtx_unlock(sc->sim_lock); tw_osli_dbg_dprintf(3, sc, "exiting"); return(0); }
/* * Attach all the sub-devices we can find */ int adv_attach(struct adv_softc *adv) { struct ccb_setasync *csa; int max_sg; /* * Allocate an array of ccb mapping structures. We put the * index of the ccb_info structure into the queue representing * a transaction and use it for mapping the queue to the * upper level SCSI transaction it represents. */ adv->ccb_infos = kmalloc(sizeof(*adv->ccb_infos) * adv->max_openings, M_DEVBUF, M_WAITOK); adv->init_level++; /* * Create our DMA tags. These tags define the kinds of device * accessible memory allocations and memory mappings we will * need to perform during normal operation. * * Unless we need to further restrict the allocation, we rely * on the restrictions of the parent dmat, hence the common * use of MAXADDR and MAXSIZE. * * The ASC boards use chains of "queues" (the transactional * resources on the board) to represent long S/G lists. * The first queue represents the command and holds a * single address and data pair. The queues that follow * can each hold ADV_SG_LIST_PER_Q entries. Given the * total number of queues, we can express the largest * transaction we can map. We reserve a few queues for * error recovery. Take those into account as well. * * There is a way to take an interrupt to download the * next batch of S/G entries if there are more than 255 * of them (the counter in the queue structure is a u_int8_t). * We don't use this feature, so limit the S/G list size * accordingly. */ max_sg = (adv->max_openings - ADV_MIN_FREE_Q - 1) * ADV_SG_LIST_PER_Q; if (max_sg > 255) max_sg = 255; /* DMA tag for mapping buffers into device visible space. */ if (bus_dma_tag_create(adv->parent_dmat, /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/MAXPHYS, /*nsegments*/max_sg, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/BUS_DMA_ALLOCNOW, &adv->buffer_dmat) != 0) { return (ENXIO); } adv->init_level++; /* DMA tag for our sense buffers */ if (bus_dma_tag_create(adv->parent_dmat, /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, sizeof(struct scsi_sense_data)*adv->max_openings, /*nsegments*/1, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, &adv->sense_dmat) != 0) { return (ENXIO); } adv->init_level++; /* Allocation for our sense buffers */ if (bus_dmamem_alloc(adv->sense_dmat, (void *)&adv->sense_buffers, BUS_DMA_NOWAIT, &adv->sense_dmamap) != 0) { return (ENOMEM); } adv->init_level++; /* And permanently map them */ bus_dmamap_load(adv->sense_dmat, adv->sense_dmamap, adv->sense_buffers, sizeof(struct scsi_sense_data)*adv->max_openings, adv_map, &adv->sense_physbase, /*flags*/0); adv->init_level++; /* * Fire up the chip */ if (adv_start_chip(adv) != 1) { kprintf("adv%d: Unable to start on board processor. Aborting.\n", adv->unit); return (ENXIO); } /* * Construct our SIM entry. */ adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv, adv->unit, &sim_mplock, 1, adv->max_openings, NULL); if (adv->sim == NULL) return (ENOMEM); /* * Register the bus. * * XXX Twin Channel EISA Cards??? */ if (xpt_bus_register(adv->sim, 0) != CAM_SUCCESS) { cam_sim_free(adv->sim); return (ENXIO); } if (xpt_create_path(&adv->path, /*periph*/NULL, cam_sim_path(adv->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(adv->sim)); cam_sim_free(adv->sim); return (ENXIO); } csa = &xpt_alloc_ccb()->csa; xpt_setup_ccb(&csa->ccb_h, adv->path, /*priority*/5); csa->ccb_h.func_code = XPT_SASYNC_CB; csa->event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; csa->callback = advasync; csa->callback_arg = adv; xpt_action((union ccb *)csa); xpt_free_ccb(&csa->ccb_h); return (0); }
/* * Function name: twa_cam_setup * Description: Attaches the driver to CAM. * * Input: sc -- ptr to per ctlr structure * Output: None * Return value: 0 -- success * non-zero-- failure */ int twa_cam_setup(struct twa_softc *sc) { struct cam_devq *devq; struct ccb_setasync csa; twa_dbg_dprint(3, sc, "sc = %p", sc); /* * Create the device queue for our SIM. */ devq = cam_simq_alloc(TWA_Q_LENGTH); if (devq == NULL) return(ENOMEM); /* * Create a SIM entry. Though we can support TWA_Q_LENGTH simultaneous * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so * that we always have a request packet available to service attention * interrupts. */ twa_dbg_dprint(3, sc, "Calling cam_sim_alloc"); sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc, device_get_unit(sc->twa_bus_dev), TWA_Q_LENGTH - 1, 1, devq); if (sc->twa_sim == NULL) { cam_simq_free(devq); return(ENOMEM); } /* * Register the bus. */ twa_dbg_dprint(3, sc, "Calling xpt_bus_register"); if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) { cam_sim_free(sc->twa_sim, TRUE); sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */ return(ENXIO); } twa_dbg_dprint(3, sc, "Calling xpt_create_path"); if (xpt_create_path(&sc->twa_path, NULL, cam_sim_path(sc->twa_sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path (sc->twa_sim)); cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */ return(ENXIO); } twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb"); xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE; csa.callback = twa_async; csa.callback_arg = sc; xpt_action((union ccb *)&csa); twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan"); /* * Request a bus scan, so that CAM gets to know of * the logical units that we control. */ twa_request_bus_scan(sc); twa_dbg_dprint(3, sc, "Exiting"); return(0); }
static int ahbxptattach(struct ahb_softc *ahb) { struct cam_devq *devq; struct ecb *ecb; u_int i; /* Remeber who are we on the scsi bus */ ahb->scsi_id = ahb_inb(ahb, SCSIDEF) & HSCSIID; /* Use extended translation?? */ ahb->extended_trans = ahb_inb(ahb, RESV1) & EXTENDED_TRANS; /* Fetch adapter inquiry data */ ecb = ahbecbget(ahb); /* Always succeeds - no outstanding commands */ ecb->hecb.opcode = ECBOP_READ_HA_INQDATA; ecb->hecb.flag_word1 = FW1_SUPPRESS_URUN_ERR|FW1_ERR_STATUS_BLK_ONLY; ecb->hecb.data_ptr = ahb->ha_inq_physbase; ecb->hecb.data_len = sizeof(struct ha_inquiry_data); ecb->hecb.sense_ptr = 0; ecb->state = ECB_ACTIVE; /* Tell the adapter about this command */ ahbqueuembox(ahb, ahbecbvtop(ahb, ecb), ATTN_STARTECB|ahb->scsi_id); /* Poll for interrupt completion */ for (i = 1000; ecb->state != ECB_FREE && i != 0; i--) { ahbintr(ahb); DELAY(1000); } ahb->num_ecbs = MIN(ahb->num_ecbs, ahb->ha_inq_data->scsi_data.spc2_flags); printf("ahb%ld: %.8s %s SCSI Adapter, FW Rev. %.4s, ID=%d, %d ECBs\n", ahb->unit, ahb->ha_inq_data->scsi_data.product, (ahb->ha_inq_data->scsi_data.flags & 0x4) ? "Differential" : "Single Ended", ahb->ha_inq_data->scsi_data.revision, ahb->scsi_id, ahb->num_ecbs); /* Restore sense paddr for future CCB clients */ ecb->hecb.sense_ptr = ahbsensepaddr(ahbecbvtop(ahb, ecb)); ahbecbfree(ahb, ecb); /* * Create the device queue for our SIM. */ devq = cam_simq_alloc(ahb->num_ecbs); if (devq == NULL) return (ENOMEM); /* * Construct our SIM entry */ ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, ahb->unit, &Giant, 2, ahb->num_ecbs, devq); if (ahb->sim == NULL) { cam_simq_free(devq); return (ENOMEM); } if (xpt_bus_register(ahb->sim, ahb->dev, 0) != CAM_SUCCESS) { cam_sim_free(ahb->sim, /*free_devq*/TRUE); return (ENXIO); } if (xpt_create_path(&ahb->path, /*periph*/NULL, cam_sim_path(ahb->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(ahb->sim)); cam_sim_free(ahb->sim, /*free_devq*/TRUE); return (ENXIO); } /* * Allow the board to generate interrupts. */ ahb_outb(ahb, INTDEF, ahb_inb(ahb, INTDEF) | INTEN); return (0); }
int ata_attach(device_t dev) { struct ata_channel *ch = device_get_softc(dev); int error, rid; struct cam_devq *devq; const char *res; char buf[64]; int i, mode; /* check that we have a virgin channel to attach */ if (ch->r_irq) return EEXIST; /* initialize the softc basics */ ch->dev = dev; ch->state = ATA_IDLE; bzero(&ch->state_mtx, sizeof(struct mtx)); mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF); TASK_INIT(&ch->conntask, 0, ata_conn_event, dev); for (i = 0; i < 16; i++) { ch->user[i].revision = 0; snprintf(buf, sizeof(buf), "dev%d.sata_rev", i); if (resource_int_value(device_get_name(dev), device_get_unit(dev), buf, &mode) != 0 && resource_int_value(device_get_name(dev), device_get_unit(dev), "sata_rev", &mode) != 0) mode = -1; if (mode >= 0) ch->user[i].revision = mode; ch->user[i].mode = 0; snprintf(buf, sizeof(buf), "dev%d.mode", i); if (resource_string_value(device_get_name(dev), device_get_unit(dev), buf, &res) == 0) mode = ata_str2mode(res); else if (resource_string_value(device_get_name(dev), device_get_unit(dev), "mode", &res) == 0) mode = ata_str2mode(res); else mode = -1; if (mode >= 0) ch->user[i].mode = mode; if (ch->flags & ATA_SATA) ch->user[i].bytecount = 8192; else ch->user[i].bytecount = MAXPHYS; ch->user[i].caps = 0; ch->curr[i] = ch->user[i]; if (ch->flags & ATA_SATA) { if (ch->pm_level > 0) ch->user[i].caps |= CTS_SATA_CAPS_H_PMREQ; if (ch->pm_level > 1) ch->user[i].caps |= CTS_SATA_CAPS_D_PMREQ; } else { if (!(ch->flags & ATA_NO_48BIT_DMA)) ch->user[i].caps |= CTS_ATA_CAPS_H_DMA48; } } callout_init(&ch->poll_callout, 1); /* allocate DMA resources if DMA HW present*/ if (ch->dma.alloc) ch->dma.alloc(dev); /* setup interrupt delivery */ rid = ATA_IRQ_RID; ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (!ch->r_irq) { device_printf(dev, "unable to allocate interrupt\n"); return ENXIO; } if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, ata_interrupt, ch, &ch->ih))) { bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq); device_printf(dev, "unable to setup interrupt\n"); return error; } if (ch->flags & ATA_PERIODIC_POLL) callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch); mtx_lock(&ch->state_mtx); /* Create the device queue for our SIM. */ devq = cam_simq_alloc(1); if (devq == NULL) { device_printf(dev, "Unable to allocate simq\n"); error = ENOMEM; goto err1; } /* Construct SIM entry */ ch->sim = cam_sim_alloc(ataaction, atapoll, "ata", ch, device_get_unit(dev), &ch->state_mtx, 1, 0, devq); if (ch->sim == NULL) { device_printf(dev, "unable to allocate sim\n"); cam_simq_free(devq); error = ENOMEM; goto err1; } if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) { device_printf(dev, "unable to register xpt bus\n"); error = ENXIO; goto err2; } if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { device_printf(dev, "unable to create path\n"); error = ENXIO; goto err3; } mtx_unlock(&ch->state_mtx); return (0); err3: xpt_bus_deregister(cam_sim_path(ch->sim)); err2: cam_sim_free(ch->sim, /*free_devq*/TRUE); ch->sim = NULL; err1: bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq); mtx_unlock(&ch->state_mtx); if (ch->flags & ATA_PERIODIC_POLL) callout_drain(&ch->poll_callout); return (error); }
static int ahci_em_attach(device_t dev) { device_t parent = device_get_parent(dev); struct ahci_controller *ctlr = device_get_softc(parent); struct ahci_enclosure *enc = device_get_softc(dev); struct cam_devq *devq; int i, c, rid, error; char buf[32]; enc->dev = dev; enc->quirks = ctlr->quirks; enc->channels = ctlr->channels; enc->ichannels = ctlr->ichannels; mtx_init(&enc->mtx, "AHCI enclosure lock", NULL, MTX_DEF); rid = 0; if (!(enc->r_memc = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) { mtx_destroy(&enc->mtx); return (ENXIO); } enc->capsem = ATA_INL(enc->r_memc, 0); rid = 1; if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) { error = ENXIO; goto err0; } if ((enc->capsem & (AHCI_EM_XMT | AHCI_EM_SMB)) == 0) { rid = 2; if (!(enc->r_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) { error = ENXIO; goto err0; } } else enc->r_memr = NULL; mtx_lock(&enc->mtx); if (ahci_em_reset(dev) != 0) { error = ENXIO; goto err1; } rid = ATA_IRQ_RID; /* Create the device queue for our SIM. */ devq = cam_simq_alloc(1); if (devq == NULL) { device_printf(dev, "Unable to allocate SIM queue\n"); error = ENOMEM; goto err1; } /* Construct SIM entry */ enc->sim = cam_sim_alloc(ahciemaction, ahciempoll, "ahciem", enc, device_get_unit(dev), &enc->mtx, 1, 0, devq); if (enc->sim == NULL) { cam_simq_free(devq); device_printf(dev, "Unable to allocate SIM\n"); error = ENOMEM; goto err1; } if (xpt_bus_register(enc->sim, dev, 0) != CAM_SUCCESS) { device_printf(dev, "unable to register xpt bus\n"); error = ENXIO; goto err2; } if (xpt_create_path(&enc->path, /*periph*/NULL, cam_sim_path(enc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { device_printf(dev, "Unable to create path\n"); error = ENXIO; goto err3; } mtx_unlock(&enc->mtx); if (bootverbose) { device_printf(dev, "Caps:%s%s%s%s%s%s%s%s\n", (enc->capsem & AHCI_EM_PM) ? " PM":"", (enc->capsem & AHCI_EM_ALHD) ? " ALHD":"", (enc->capsem & AHCI_EM_XMT) ? " XMT":"", (enc->capsem & AHCI_EM_SMB) ? " SMB":"", (enc->capsem & AHCI_EM_SGPIO) ? " SGPIO":"", (enc->capsem & AHCI_EM_SES2) ? " SES-2":"", (enc->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"", (enc->capsem & AHCI_EM_LED) ? " LED":""); } if ((enc->capsem & AHCI_EM_LED)) { for (c = 0; c < enc->channels; c++) { if ((enc->ichannels & (1 << c)) == 0) continue; for (i = 0; i < AHCI_NUM_LEDS; i++) { enc->leds[c * AHCI_NUM_LEDS + i].dev = dev; enc->leds[c * AHCI_NUM_LEDS + i].num = c * AHCI_NUM_LEDS + i; } if ((enc->capsem & AHCI_EM_ALHD) == 0) { snprintf(buf, sizeof(buf), "%s.%d.act", device_get_nameunit(parent), c); enc->leds[c * AHCI_NUM_LEDS + 0].led = led_create(ahci_em_led, &enc->leds[c * AHCI_NUM_LEDS + 0], buf); } snprintf(buf, sizeof(buf), "%s.%d.locate", device_get_nameunit(parent), c); enc->leds[c * AHCI_NUM_LEDS + 1].led = led_create(ahci_em_led, &enc->leds[c * AHCI_NUM_LEDS + 1], buf); snprintf(buf, sizeof(buf), "%s.%d.fault", device_get_nameunit(parent), c); enc->leds[c * AHCI_NUM_LEDS + 2].led = led_create(ahci_em_led, &enc->leds[c * AHCI_NUM_LEDS + 2], buf); } } return (0); err3: xpt_bus_deregister(cam_sim_path(enc->sim)); err2: cam_sim_free(enc->sim, /*free_devq*/TRUE); err1: mtx_unlock(&enc->mtx); if (enc->r_memr) bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr); err0: if (enc->r_memt) bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt); bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc); mtx_destroy(&enc->mtx); return (error); }
int tws_cam_attach(struct tws_softc *sc) { struct cam_devq *devq; TWS_TRACE_DEBUG(sc, "entry", 0, sc); /* Create a device queue for sim */ /* * if the user sets cam depth to less than 1 * cam may get confused */ if ( tws_cam_depth < 1 ) tws_cam_depth = 1; if ( tws_cam_depth > (tws_queue_depth - TWS_RESERVED_REQS) ) tws_cam_depth = tws_queue_depth - TWS_RESERVED_REQS; TWS_TRACE_DEBUG(sc, "depths,ctlr,cam", tws_queue_depth, tws_cam_depth); if ((devq = cam_simq_alloc(tws_cam_depth)) == NULL) { tws_log(sc, CAM_SIMQ_ALLOC); return(ENOMEM); } /* * Create a SIM entry. Though we can support tws_cam_depth * simultaneous requests, we claim to be able to handle only * (tws_cam_depth), so that we always have reserved requests * packet available to service ioctls and internal commands. */ sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc, device_get_unit(sc->tws_dev), #if (__FreeBSD_version >= 700000) &sc->sim_lock, #endif tws_cam_depth, 1, devq); /* 1, 1, devq); */ if (sc->sim == NULL) { cam_simq_free(devq); tws_log(sc, CAM_SIM_ALLOC); } /* Register the bus. */ mtx_lock(&sc->sim_lock); if (xpt_bus_register(sc->sim, #if (__FreeBSD_version >= 700000) sc->tws_dev, #endif 0) != CAM_SUCCESS) { cam_sim_free(sc->sim, TRUE); /* passing true will free the devq */ sc->sim = NULL; /* so cam_detach will not try to free it */ mtx_unlock(&sc->sim_lock); tws_log(sc, TWS_XPT_BUS_REGISTER); return(ENXIO); } if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sc->sim)); /* Passing TRUE to cam_sim_free will free the devq as well. */ cam_sim_free(sc->sim, TRUE); tws_log(sc, TWS_XPT_CREATE_PATH); mtx_unlock(&sc->sim_lock); return(ENXIO); } mtx_unlock(&sc->sim_lock); return(0); }