Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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 #4
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);
}
Example #5
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);
}
Example #6
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);
}
Example #7
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;
}
Example #8
0
/*
 * 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);
}
Example #9
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);
}
Example #10
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);
}
Example #11
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);
}
Example #12
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 #13
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);
}
Example #14
0
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);
}
Example #15
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);
}
Example #16
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);
}
Example #17
0
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);
}
Example #19
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);
}
Example #20
0
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);
}
Example #21
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);
}
Example #22
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);
}
Example #23
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);
}
Example #24
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);
}
Example #25
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);
}
Example #26
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);
}
Example #27
0
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);
}
Example #28
0
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);
}