Example #1
0
/********************************************************************************
 * 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);
}
Example #2
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);
}
Example #3
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);
}
Example #4
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;
	}
}
Example #5
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);
}
Example #6
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);
}
Example #8
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);
}
Example #9
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);
}