Пример #1
0
/*
 * mrsas_bus_scan:	Perform bus scan
 * input:			Adapter instance soft state
 *
 * This mrsas_bus_scan function is needed for FreeBSD 7.x.  Also, it should not
 * be called in FreeBSD 8.x and later versions, where the bus scan is
 * automatic.
 */
int
mrsas_bus_scan(struct mrsas_softc *sc)
{
    union ccb *ccb_0;
    union ccb *ccb_1;

    if ((ccb_0 = xpt_alloc_ccb()) == NULL) {
        return (ENOMEM);
    }
    if ((ccb_1 = xpt_alloc_ccb()) == NULL) {
        xpt_free_ccb(ccb_0);
        return (ENOMEM);
    }
    mtx_lock(&sc->sim_lock);
    if (xpt_create_path(&ccb_0->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_0),
                        CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
        xpt_free_ccb(ccb_0);
        xpt_free_ccb(ccb_1);
        mtx_unlock(&sc->sim_lock);
        return (EIO);
    }
    if (xpt_create_path(&ccb_1->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_1),
                        CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
        xpt_free_ccb(ccb_0);
        xpt_free_ccb(ccb_1);
        mtx_unlock(&sc->sim_lock);
        return (EIO);
    }
    mtx_unlock(&sc->sim_lock);
    xpt_rescan(ccb_0);
    xpt_rescan(ccb_1);

    return (0);
}
/*
 * mrsas_bus_scan:           Perform bus scan 
 * input:                    Adapter instance soft state  
 *
 * This mrsas_bus_scan function is needed for FreeBSD 7.x.  Also, it should
 * not be called in FreeBSD 8.x and later versions, where the bus scan is 
 * automatic. 
 */ 
int mrsas_bus_scan(struct mrsas_softc *sc)
{
    union ccb *ccb_0;
    union ccb *ccb_1;

    lockmgr(&sc->sim_lock, LK_EXCLUSIVE);
    if ((ccb_0 = xpt_alloc_ccb()) == NULL) {
        lockmgr(&sc->sim_lock, LK_RELEASE);
        return(ENOMEM);
    }

    if ((ccb_1 = xpt_alloc_ccb()) == NULL) {
	xpt_free_ccb(ccb_0);
        lockmgr(&sc->sim_lock, LK_RELEASE);
        return(ENOMEM);
    } 

    if (xpt_create_path(&ccb_0->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_0),
            CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP){
        xpt_free_ccb(ccb_0);
        xpt_free_ccb(ccb_1);
        lockmgr(&sc->sim_lock, LK_RELEASE);
        return(EIO);
    }

    if (xpt_create_path(&ccb_1->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_1),
            CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP){
        xpt_free_ccb(ccb_0);
        xpt_free_ccb(ccb_1);
        lockmgr(&sc->sim_lock, LK_RELEASE);
        return(EIO);
    }

    xpt_setup_ccb(&ccb_0->ccb_h, ccb_0->ccb_h.path, 5/*priority (low)*/);
    ccb_0->ccb_h.func_code = XPT_SCAN_BUS;
    ccb_0->ccb_h.cbfcnp = mrsas_rescan_callback;
    ccb_0->crcn.flags = CAM_FLAG_NONE;
    xpt_action(ccb_0); /* scan is now in progress */

    xpt_setup_ccb(&ccb_1->ccb_h, ccb_1->ccb_h.path, 5/*priority (low)*/);
    ccb_1->ccb_h.func_code = XPT_SCAN_BUS;
    ccb_1->ccb_h.cbfcnp = mrsas_rescan_callback;
    ccb_1->crcn.flags = CAM_FLAG_NONE;
    xpt_action(ccb_1); /* scan is now in progress */

    lockmgr(&sc->sim_lock, LK_RELEASE);

    return(0);
}
Пример #3
0
static void
cfcs_onoffline(void *arg, int online)
{
	struct cfcs_softc *softc;
	union ccb *ccb;

	softc = (struct cfcs_softc *)arg;

	mtx_lock(&softc->lock);
	softc->online = online;

	ccb = xpt_alloc_ccb_nowait();
	if (ccb == NULL) {
		printf("%s: unable to allocate CCB for rescan\n", __func__);
		goto bailout;
	}

	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
			    cam_sim_path(softc->sim), CAM_TARGET_WILDCARD,
			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		printf("%s: can't allocate path for rescan\n", __func__);
		xpt_free_ccb(ccb);
		goto bailout;
	}
	xpt_rescan(ccb);

bailout:
	mtx_unlock(&softc->lock);
}
Пример #4
0
/*
 * Function name:	tw_osli_request_bus_scan
 * Description:		Requests CAM for a scan of the bus.
 *
 * Input:		sc	-- ptr to per ctlr structure
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_osli_request_bus_scan(struct twa_softc *sc)
{
	union ccb	*ccb;

	tw_osli_dbg_dprintf(3, sc, "entering");

	/* If we get here before sc->sim is initialized, return an error. */
	if (!(sc->sim))
		return(ENXIO);
	if ((ccb = xpt_alloc_ccb()) == NULL)
		return(ENOMEM);
	lockmgr(sc->sim_lock, LK_EXCLUSIVE);
	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		xpt_free_ccb(ccb);
		lockmgr(sc->sim_lock, LK_RELEASE);
		return(EIO);
	}

	xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
	ccb->ccb_h.func_code = XPT_SCAN_BUS;
	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
	ccb->crcn.flags = CAM_FLAG_NONE;
	xpt_action(ccb);

	lockmgr(sc->sim_lock, LK_RELEASE);
	return(0);
}
Пример #5
0
static void *
nvme_sim_new_ns(struct nvme_namespace *ns, void *sc_arg)
{
	struct nvme_sim_softc *sc = sc_arg;
	struct nvme_controller *ctrlr = sc->s_ctrlr;
	union ccb *ccb;

	mtx_lock(&ctrlr->lock);

	ccb = xpt_alloc_ccb_nowait();
	if (ccb == NULL) {
		printf("unable to alloc CCB for rescan\n");
		return (NULL);
	}

	if (xpt_create_path(&ccb->ccb_h.path, /*periph*/NULL,
	    cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) {
		printf("unable to create path for rescan\n");
		xpt_free_ccb(ccb);
		return (NULL);
	}

	xpt_rescan(ccb);

	mtx_unlock(&ctrlr->lock);

	return (ns);
}
Пример #6
0
static void
scan_callback(struct cam_periph *periph, union ccb *ccb)
{
     isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0;

     debug_called(8);

     xpt_free_ccb(ccb);

     if(sp->flags & ISC_SCANWAIT) {
	  sp->flags &= ~ISC_SCANWAIT;
	  wakeup(sp);
     }
}
Пример #7
0
/*
 * Use an engineering request to initiate a target scan for devices
 * behind a port multiplier.
 *
 * An asynchronous bus scan is used to avoid reentrancy issues.
 */
static void
ahci_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
{
	struct ahci_port *ap = ccb->ccb_h.sim_priv.entries[0].ptr;

	if (ccb->ccb_h.func_code == XPT_SCAN_BUS) {
		ap->ap_flags &= ~AP_F_SCAN_RUNNING;
		if (ap->ap_flags & AP_F_SCAN_REQUESTED) {
			ap->ap_flags &= ~AP_F_SCAN_REQUESTED;
			ahci_cam_rescan(ap);
		}
		ap->ap_flags |= AP_F_SCAN_COMPLETED;
		wakeup(&ap->ap_flags);
	}
	xpt_free_ccb(ccb);
}
Пример #8
0
static void
nvme_sim_rescan_target(struct nvme_controller *ctrlr, struct cam_path *path)
{
	union ccb *ccb;

	ccb = xpt_alloc_ccb_nowait();
	if (ccb == NULL) {
		printf("unable to alloc CCB for rescan\n");
		return;
	}

	if (xpt_clone_path(&ccb->ccb_h.path, path) != CAM_REQ_CMP) {
		printf("unable to copy path for rescan\n");
		xpt_free_ccb(ccb);
		return;
	}

	xpt_rescan(ccb);
}
Пример #9
0
int
tws_bus_scan(struct tws_softc *sc)
{
    union ccb       *ccb;

    TWS_TRACE_DEBUG(sc, "entry", sc, 0);
    if (!(sc->sim))
        return(ENXIO);
    ccb = xpt_alloc_ccb();
    mtx_lock(&sc->sim_lock);
    if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
                  CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
	mtx_unlock(&sc->sim_lock);
        xpt_free_ccb(ccb);
        return(EIO);
    }
    xpt_rescan(ccb);
    mtx_unlock(&sc->sim_lock);
    return(0);
}
Пример #10
0
void
cam_sim_free(struct cam_sim *sim, int free_devq)
{
	union ccb *ccb;
	int error;

	mtx_assert(sim->mtx, MA_OWNED);
	sim->refcount--;
	if (sim->refcount > 0) {
		error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0);
		KASSERT(error == 0, ("invalid error value for msleep(9)"));
	}

	KASSERT(sim->refcount == 0, ("sim->refcount == 0"));

	while ((ccb = (union ccb *)SLIST_FIRST(&sim->ccb_freeq)) != NULL) {
		SLIST_REMOVE_HEAD(&sim->ccb_freeq, xpt_links.sle);
		xpt_free_ccb(ccb);
	}
	if (free_devq)
		cam_simq_free(sim->devq);
	free(sim, M_CAMSIM);
}
Пример #11
0
static void
mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
{
	struct mpssas_softc *sassc;
	char path_str[64];

	sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;

	xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
	mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
	    path_str);

	if (done_ccb == NULL)
		return;

	/*
	 * Nothing more to do except free the CCB and path.  If the command
	 * timed out, an abort reset, then target reset will be issued during
	 * the SCSI Command process.
	 */
	xpt_free_path(done_ccb->ccb_h.path);
	xpt_free_ccb(done_ccb);
}
Пример #12
0
/*
 * Function name:	tw_osli_request_bus_scan
 * Description:		Requests CAM for a scan of the bus.
 *
 * Input:		sc	-- ptr to per ctlr structure
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
TW_INT32
tw_osli_request_bus_scan(struct twa_softc *sc)
{
	union ccb	*ccb;

	tw_osli_dbg_dprintf(3, sc, "entering");

	/* If we get here before sc->sim is initialized, return an error. */
	if (!(sc->sim))
		return(ENXIO);
	if ((ccb = xpt_alloc_ccb()) == NULL)
		return(ENOMEM);
	mtx_lock(sc->sim_lock);
	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		xpt_free_ccb(ccb);
		mtx_unlock(sc->sim_lock);
		return(EIO);
	}

	xpt_rescan(ccb);
	mtx_unlock(sc->sim_lock);
	return(0);
}
Пример #13
0
static void
ata_conn_event(void *context, int dummy)
{
	device_t dev = (device_t)context;
	struct ata_channel *ch = device_get_softc(dev);
	union ccb *ccb;

	mtx_lock(&ch->state_mtx);
	if (ch->sim == NULL) {
		mtx_unlock(&ch->state_mtx);
		return;
	}
	ata_reinit(dev);
	if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
		return;
	if (xpt_create_path(&ccb->ccb_h.path, NULL,
	    cam_sim_path(ch->sim),
	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		xpt_free_ccb(ccb);
		return;
	}
	xpt_rescan(ccb);
	mtx_unlock(&ch->state_mtx);
}
Пример #14
0
static int
cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
    struct thread *td, d_ioctl_t *cbfnp)
{
	union ccb		*ccb;
	struct ccb_hdr		*hdr;
	struct ccb_hdr_0x17	*hdr17;
	uint8_t			*ccbb, *ccbb17;
	u_int			error;

	hdr17 = (struct ccb_hdr_0x17 *)addr;
	ccb = xpt_alloc_ccb();
	hdr = &ccb->ccb_h;

	hdr->pinfo = hdr17->pinfo;
	hdr->xpt_links = hdr17->xpt_links;
	hdr->sim_links = hdr17->sim_links;
	hdr->periph_links = hdr17->periph_links;
	hdr->retry_count = hdr17->retry_count;
	hdr->cbfcnp = hdr17->cbfcnp;
	hdr->func_code = hdr17->func_code;
	hdr->status = hdr17->status;
	hdr->path = hdr17->path;
	hdr->path_id = hdr17->path_id;
	hdr->target_id = hdr17->target_id;
	hdr->target_lun = hdr17->target_lun;
	hdr->flags = hdr17->flags;
	hdr->xflags = 0;
	hdr->periph_priv = hdr17->periph_priv;
	hdr->sim_priv = hdr17->sim_priv;
	hdr->timeout = hdr17->timeout;
	hdr->softtimeout.tv_sec = 0;
	hdr->softtimeout.tv_usec = 0;

	ccbb = (uint8_t *)&hdr[1];
	ccbb17 = (uint8_t *)&hdr17[1];
	if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
		struct ccb_trans_settings *cts;
		struct ccb_trans_settings_0x17 *cts17;

		cts = &ccb->cts;
		cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
		cts->type = cts17->type;
		cts->protocol = cts17->protocol;
		cts->protocol_version = cts17->protocol_version;
		cts->transport = cts17->transport;
		cts->transport_version = cts17->transport_version;
		bcopy(&cts17->proto_specific, &cts->proto_specific,
		    sizeof(cts17->proto_specific));
		bcopy(&cts17->xport_specific, &cts->xport_specific,
		    sizeof(cts17->xport_specific));
	} else {
		bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN);
	}

	error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);

	hdr17->pinfo = hdr->pinfo;
	hdr17->xpt_links = hdr->xpt_links;
	hdr17->sim_links = hdr->sim_links;
	hdr17->periph_links = hdr->periph_links;
	hdr17->retry_count = hdr->retry_count;
	hdr17->cbfcnp = hdr->cbfcnp;
	hdr17->func_code = hdr->func_code;
	hdr17->status = hdr->status;
	hdr17->path = hdr->path;
	hdr17->path_id = hdr->path_id;
	hdr17->target_id = hdr->target_id;
	hdr17->target_lun = hdr->target_lun;
	hdr17->flags = hdr->flags;
	hdr17->periph_priv = hdr->periph_priv;
	hdr17->sim_priv = hdr->sim_priv;
	hdr17->timeout = hdr->timeout;

	if (ccb->ccb_h.func_code == XPT_PATH_INQ) {
		struct ccb_pathinq	*cpi;
		struct ccb_pathinq_0x17 *cpi17;

		/* The PATH_INQ only needs special handling on the way out */
		cpi = &ccb->cpi;
		cpi17 = (struct ccb_pathinq_0x17 *)hdr17;
		cpi17->version_num = cpi->version_num;
		cpi17->hba_inquiry = cpi->hba_inquiry;
		cpi17->target_sprt = (u_int8_t)cpi->target_sprt;
		cpi17->hba_misc = (u_int8_t)cpi->hba_misc;
		cpi17->hba_eng_cnt = cpi->hba_eng_cnt;
		bcopy(&cpi->vuhba_flags[0], &cpi17->vuhba_flags[0], VUHBALEN);
		cpi17->max_target = cpi->max_target;
		cpi17->max_lun = cpi->max_lun;
		cpi17->async_flags = cpi->async_flags;
		cpi17->hpath_id = cpi->hpath_id;
		cpi17->initiator_id = cpi->initiator_id;
		bcopy(&cpi->sim_vid[0], &cpi17->sim_vid[0], SIM_IDLEN);
		bcopy(&cpi->hba_vid[0], &cpi17->hba_vid[0], HBA_IDLEN);
		bcopy(&cpi->dev_name[0], &cpi17->dev_name[0], DEV_IDLEN);
		cpi17->unit_number = cpi->unit_number;
		cpi17->bus_id = cpi->bus_id;
		cpi17->base_transfer_speed = cpi->base_transfer_speed;
		cpi17->protocol = cpi->protocol;
		cpi17->protocol_version = cpi->protocol_version;
		cpi17->transport = cpi->transport;
		cpi17->transport_version = cpi->transport_version;
		bcopy(&cpi->xport_specific, &cpi17->xport_specific,
		    PATHINQ_SETTINGS_SIZE);
		cpi17->maxio = cpi->maxio;
		cpi17->hba_vendor = cpi->hba_vendor;
		cpi17->hba_device = cpi->hba_device;
		cpi17->hba_subvendor = cpi->hba_subvendor;
		cpi17->hba_subdevice = cpi->hba_subdevice;
	} else if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
		struct ccb_trans_settings *cts;
		struct ccb_trans_settings_0x17 *cts17;

		cts = &ccb->cts;
		cts17 = (struct ccb_trans_settings_0x17 *)hdr17;
		cts17->type = cts->type;
		cts17->protocol = cts->protocol;
		cts17->protocol_version = cts->protocol_version;
		cts17->transport = cts->transport;
		cts17->transport_version = cts->transport_version;
		bcopy(&cts->proto_specific, &cts17->proto_specific,
		    sizeof(cts17->proto_specific));
		bcopy(&cts->xport_specific, &cts17->xport_specific,
		    sizeof(cts17->xport_specific));
	} else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
		/* Copy the rest of the header over */
		bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);

		cam_compat_translate_dev_match_0x18(ccb);
	} else {
		bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
	}

	xpt_free_ccb(ccb);

	return (error);
}
Пример #15
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);
}
Пример #16
0
/**
 * mpssas_SSU_to_SATA_devices 
 * @sc: per adapter object
 *
 * Looks through the target list and issues a StartStopUnit SCSI command to each
 * SATA direct-access device.  This helps to ensure that data corruption is
 * avoided when the system is being shut down.  This must be called after the IR
 * System Shutdown RAID Action is sent if in IR mode.
 *
 * Return nothing.
 */
static void
mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
{
	struct mpssas_softc *sassc = sc->sassc;
	union ccb *ccb;
	path_id_t pathid = cam_sim_path(sassc->sim);
	target_id_t targetid;
	struct mpssas_target *target;
	char path_str[64];
	struct timeval cur_time, start_time;

	/*
	 * For each target, issue a StartStopUnit command to stop the device.
	 */
	sc->SSU_started = TRUE;
	sc->SSU_refcount = 0;
	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
		target = &sassc->targets[targetid];
		if (target->handle == 0x0) {
			continue;
		}

		ccb = xpt_alloc_ccb_nowait();
		if (ccb == NULL) {
			mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop "
			    "unit.\n");
			return;
		}

		/*
		 * The stop_at_shutdown flag will be set if this device is
		 * a SATA direct-access end device.
		 */
		if (target->stop_at_shutdown) {
			if (xpt_create_path(&ccb->ccb_h.path,
			    xpt_periph, pathid, targetid,
			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
				mps_dprint(sc, MPS_FAULT, "Unable to create "
				    "LUN path to stop unit.\n");
				xpt_free_ccb(ccb);
				return;
			}
			xpt_path_string(ccb->ccb_h.path, path_str,
			    sizeof(path_str));

			mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s "
			    "handle %d\n", path_str, target->handle);
			
			/*
			 * Issue a START STOP UNIT command for the target.
			 * Increment the SSU counter to be used to count the
			 * number of required replies.
			 */
			mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n");
			sc->SSU_refcount++;
			ccb->ccb_h.target_id =
			    xpt_path_target_id(ccb->ccb_h.path);
			ccb->ccb_h.ppriv_ptr1 = sassc;
			scsi_start_stop(&ccb->csio,
			    /*retries*/0,
			    mpssas_stop_unit_done,
			    MSG_SIMPLE_Q_TAG,
			    /*start*/FALSE,
			    /*load/eject*/0,
			    /*immediate*/FALSE,
			    MPS_SENSE_LEN,
			    /*timeout*/10000);
			xpt_action(ccb);
		}
	}

	/*
	 * Wait until all of the SSU commands have completed or time has
	 * expired (60 seconds).  Pause for 100ms each time through.  If any
	 * command times out, the target will be reset in the SCSI command
	 * timeout routine.
	 */
	getmicrotime(&start_time);
	while (sc->SSU_refcount) {
		pause("mpswait", hz/10);
		
		getmicrotime(&cur_time);
		if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
			mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
			    "for SSU commands to complete.\n");
			break;
		}
	}
}
static void
mrsas_rescan_callback(struct cam_periph *periph, union ccb *ccb)
{
	xpt_free_path(ccb->ccb_h.path);
	xpt_free_ccb(ccb);
}
Пример #18
0
static int
cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
    struct thread *td, d_ioctl_t *cbfnp)
{
	union ccb		*ccb;
	struct ccb_hdr		*hdr;
	struct ccb_hdr_0x18	*hdr18;
	uint8_t			*ccbb, *ccbb18;
	u_int			error;

	hdr18 = (struct ccb_hdr_0x18 *)addr;
	ccb = xpt_alloc_ccb();
	hdr = &ccb->ccb_h;

	hdr->pinfo = hdr18->pinfo;
	hdr->xpt_links = hdr18->xpt_links;
	hdr->sim_links = hdr18->sim_links;
	hdr->periph_links = hdr18->periph_links;
	hdr->retry_count = hdr18->retry_count;
	hdr->cbfcnp = hdr18->cbfcnp;
	hdr->func_code = hdr18->func_code;
	hdr->status = hdr18->status;
	hdr->path = hdr18->path;
	hdr->path_id = hdr18->path_id;
	hdr->target_id = hdr18->target_id;
	hdr->target_lun = hdr18->target_lun;
	if (hdr18->xflags & CAM_EXTLUN_VALID_0x18)
		hdr->target_lun = hdr18->ext_lun;
	hdr->flags = hdr18->flags;
	hdr->xflags = hdr18->xflags;
	hdr->periph_priv = hdr18->periph_priv;
	hdr->sim_priv = hdr18->sim_priv;
	hdr->timeout = hdr18->timeout;
	hdr->softtimeout.tv_sec = 0;
	hdr->softtimeout.tv_usec = 0;

	ccbb = (uint8_t *)&hdr[1];
	ccbb18 = (uint8_t *)&hdr18[1];
	if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) {
		struct ccb_trans_settings *cts;
		struct ccb_trans_settings_0x18 *cts18;

		cts = &ccb->cts;
		cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
		cts->type = cts18->type;
		cts->protocol = cts18->protocol;
		cts->protocol_version = cts18->protocol_version;
		cts->transport = cts18->transport;
		cts->transport_version = cts18->transport_version;
		bcopy(&cts18->proto_specific, &cts->proto_specific,
		    sizeof(cts18->proto_specific));
		bcopy(&cts18->xport_specific, &cts->xport_specific,
		    sizeof(cts18->xport_specific));
	} else {
		bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN);
	}

	error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);

	hdr18->pinfo = hdr->pinfo;
	hdr18->xpt_links = hdr->xpt_links;
	hdr18->sim_links = hdr->sim_links;
	hdr18->periph_links = hdr->periph_links;
	hdr18->retry_count = hdr->retry_count;
	hdr18->cbfcnp = hdr->cbfcnp;
	hdr18->func_code = hdr->func_code;
	hdr18->status = hdr->status;
	hdr18->path = hdr->path;
	hdr18->path_id = hdr->path_id;
	hdr18->target_id = hdr->target_id;
	hdr18->target_lun = hdr->target_lun;
	hdr18->ext_lun = hdr->target_lun;
	hdr18->flags = hdr->flags;
	hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18;
	hdr18->periph_priv = hdr->periph_priv;
	hdr18->sim_priv = hdr->sim_priv;
	hdr18->timeout = hdr->timeout;

	if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) {
		struct ccb_trans_settings *cts;
		struct ccb_trans_settings_0x18 *cts18;

		cts = &ccb->cts;
		cts18 = (struct ccb_trans_settings_0x18 *)hdr18;
		cts18->type = cts->type;
		cts18->protocol = cts->protocol;
		cts18->protocol_version = cts->protocol_version;
		cts18->transport = cts->transport;
		cts18->transport_version = cts->transport_version;
		bcopy(&cts->proto_specific, &cts18->proto_specific,
		    sizeof(cts18->proto_specific));
		bcopy(&cts->xport_specific, &cts18->xport_specific,
		    sizeof(cts18->xport_specific));
	} else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
		bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
		cam_compat_translate_dev_match_0x18(ccb);
	} else {
		bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
	}

	xpt_free_ccb(ccb);

	return (error);
}