/******************************************************************************** * Disconnect ourselves from CAM */ static int amr_cam_detach(device_t dev) { struct amr_softc *sc; int chn; sc = device_get_softc(dev); lockmgr(&sc->amr_list_lock, LK_EXCLUSIVE); for (chn = 0; chn < sc->amr_maxchan; chn++) { /* * If a sim was allocated for this channel, free it */ if (sc->amr_cam_sim[chn] != NULL) { xpt_bus_deregister(cam_sim_path(sc->amr_cam_sim[chn])); cam_sim_free(sc->amr_cam_sim[chn]); } } lockmgr(&sc->amr_list_lock, LK_RELEASE); /* Now free the devq */ if (sc->amr_cam_devq != NULL) cam_simq_release(sc->amr_cam_devq); 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_release(devq); device_printf(sc->amr_dev, "CAM SIM attach failed\n"); return(ENOMEM); } /* register the bus ID so we can get it later */ lockmgr(&sc->amr_list_lock, LK_EXCLUSIVE); error = xpt_bus_register(sc->amr_cam_sim[chn], chn); lockmgr(&sc->amr_list_lock, LK_RELEASE); 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); }
/* * Note: the devq is still used by individual peripherals even if the * backend sim disappears, so do not destroy it until the sim itself * is no longer needed. */ void cam_sim_release(struct cam_sim *sim, int flags) { if (flags & CAM_SIM_SOFTC) sim->softc = NULL; if (sim->refcount == 1) { if (sim->devq) { cam_simq_release(sim->devq); sim->devq = NULL; } sim->refcount = 0; kfree(sim, M_CAMSIM); } else { --sim->refcount; } }
/* * 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 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); cam_simq_release(sc->devq); if (sc->sim == NULL) { device_printf(dev, "CAM SIM attach failed\n"); return (EINVAL); } lockmgr(&mfisc->mfi_io_lock, LK_EXCLUSIVE); if (xpt_bus_register(sc->sim, 0) != 0) { device_printf(dev, "XPT bus registration failed\n"); cam_sim_free(sc->sim); lockmgr(&mfisc->mfi_io_lock, LK_RELEASE); return (EINVAL); } lockmgr(&mfisc->mfi_io_lock, LK_RELEASE); return (0); }
/** * 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); }
/* * 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_INT32 error; 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); cam_simq_release(devq); if (sc->sim == NULL) { 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"); 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 */ tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2102, "Failed to register the bus", ENXIO); lockmgr(sc->sim_lock, LK_RELEASE); 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)); cam_sim_free(sc->sim); 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, 0x2103, "Failed to create path", ENXIO); lockmgr(sc->sim_lock, LK_RELEASE); return(ENXIO); } lockmgr(sc->sim_lock, LK_RELEASE); tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan"); /* * Request a bus scan, so that CAM gets to know of * the logical units that we control. */ if ((error = tw_osli_request_bus_scan(sc))) tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2104, "Bus scan request to CAM failed", error); tw_osli_dbg_dprintf(3, sc, "exiting"); return(0); }
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); }