static void
isci_io_request_construct(void *arg, bus_dma_segment_t *seg, int nseg,
    int error)
{
	union ccb *ccb;
	struct ISCI_IO_REQUEST *io_request = (struct ISCI_IO_REQUEST *)arg;
	SCI_REMOTE_DEVICE_HANDLE_T *device = io_request->parent.remote_device_handle;
	SCI_STATUS status;

	io_request->num_segments = nseg;
	io_request->sge = seg;
	ccb = io_request->ccb;

	/* XXX More cleanup is needed here */
	if ((nseg == 0) || (error != 0)) {
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		return;
	}

	status = scif_io_request_construct(
	    io_request->parent.controller_handle,
	    io_request->parent.remote_device_handle,
	    SCI_CONTROLLER_INVALID_IO_TAG, (void *)io_request,
	    (void *)((char*)io_request + sizeof(struct ISCI_IO_REQUEST)),
	    &io_request->sci_object);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(io_request->parent.controller_handle,
		    device, io_request, (SCI_IO_STATUS)status);
		return;
	}

	sci_object_set_association(io_request->sci_object, io_request);

	bus_dmamap_sync(io_request->parent.dma_tag, io_request->parent.dma_map,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);

	status = (SCI_STATUS)scif_controller_start_io(
	    io_request->parent.controller_handle, device,
	    io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(io_request->parent.controller_handle,
		    device, io_request, (SCI_IO_STATUS)status);
		return;
	}

	if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
		callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
		    isci_io_request_timeout, io_request);
}
Esempio n. 2
0
/**
 * @brief This user callback will inform the user that an IO request has
 *        completed.
 *
 * @param[in]  controller This parameter specifies the controller on
 *             which the IO request is completing.
 * @param[in]  remote_device This parameter specifies the remote device on
 *             which this request is completing.
 * @param[in]  io_request This parameter specifies the IO request that has
 *             completed.
 * @param[in]  completion_status This parameter specifies the results of
 *             the IO request operation.  SCI_IO_SUCCESS indicates
 *             successful completion.
 *
 * @return none
 */
void
scif_cb_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
    SCI_IO_REQUEST_HANDLE_T io_request, SCI_IO_STATUS completion_status)
{
	struct ISCI_IO_REQUEST *isci_request =
	    (struct ISCI_IO_REQUEST *)sci_object_get_association(io_request);

	scif_controller_complete_io(scif_controller, remote_device, io_request);
	isci_io_request_complete(scif_controller, remote_device, isci_request,
	    completion_status);
}
Esempio n. 3
0
void
isci_io_request_execute_smp_io(union ccb *ccb,
    struct ISCI_CONTROLLER *controller)
{
	SCI_STATUS status;
	target_id_t target_id = ccb->ccb_h.target_id;
	struct ISCI_REQUEST *request;
	struct ISCI_IO_REQUEST *io_request;
	SCI_REMOTE_DEVICE_HANDLE_T smp_device_handle;
	struct ISCI_REMOTE_DEVICE *end_device = controller->remote_device[target_id];

	/* SMP commands are sent to an end device, because SMP devices are not
	 *  exposed to the kernel.  It is our responsibility to use this method
	 *  to get the SMP device that contains the specified end device.  If
	 *  the device is direct-attached, the handle will come back NULL, and
	 *  we'll just fail the SMP_IO with DEV_NOT_THERE.
	 */
	scif_remote_device_get_containing_device(end_device->sci_object,
	    &smp_device_handle);

	if (smp_device_handle == NULL) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
		xpt_done(ccb);
		return;
	}

	if (sci_pool_empty(controller->request_pool)) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
		xpt_freeze_simq(controller->sim, 1);
		controller->is_frozen = TRUE;
		xpt_done(ccb);
		return;
	}

	ASSERT(device->is_resetting == FALSE);

	sci_pool_get(controller->request_pool, request);
	io_request = (struct ISCI_IO_REQUEST *)request;

	io_request->ccb = ccb;
	io_request->parent.remote_device_handle = smp_device_handle;

	status = isci_smp_request_construct(io_request);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(controller->scif_controller_handle,
		    smp_device_handle, io_request, (SCI_IO_STATUS)status);
		return;
	}

	sci_object_set_association(io_request->sci_object, io_request);

	status = (SCI_STATUS) scif_controller_start_io(
	    controller->scif_controller_handle, smp_device_handle,
	    io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(controller->scif_controller_handle,
		    smp_device_handle, io_request, (SCI_IO_STATUS)status);
		return;
	}

	if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
		callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
		    isci_io_request_timeout, request);
}