static int uftdi_send_data(uftdi_state_t *uf, mblk_t *data) { usb_bulk_req_t *br; int len = MBLKL(data); int rval; USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_send_data: %d 0x%x 0x%x 0x%x", len, data->b_rptr[0], (len > 1) ? data->b_rptr[1] : 0, (len > 2) ? data->b_rptr[2] : 0); ASSERT(!mutex_owned(&uf->uf_lock)); br = usb_alloc_bulk_req(uf->uf_dip, 0, USB_FLAGS_SLEEP); br->bulk_data = data; br->bulk_len = len; br->bulk_timeout = UFTDI_BULKOUT_TIMEOUT; br->bulk_cb = uftdi_bulkout_cb; br->bulk_exc_cb = uftdi_bulkout_cb; br->bulk_client_private = (usb_opaque_t)uf; br->bulk_attributes = USB_ATTRS_AUTOCLEARING; rval = usb_pipe_bulk_xfer(uf->uf_bulkout_ph, br, 0); if (rval != USB_SUCCESS) { USB_DPRINTF_L2(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_send_data: xfer failed %d", rval); br->bulk_data = NULL; usb_free_bulk_req(br); } return (rval); }
/* * start receiving data */ static int uftdi_rx_start(uftdi_state_t *uf) { usb_bulk_req_t *br; int rval; USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_rx_start"); ASSERT(mutex_owned(&uf->uf_lock)); uf->uf_bulkin_state = UFTDI_PIPE_BUSY; mutex_exit(&uf->uf_lock); br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_xfer_sz, USB_FLAGS_SLEEP); br->bulk_len = uf->uf_xfer_sz; br->bulk_timeout = UFTDI_BULKIN_TIMEOUT; br->bulk_cb = uftdi_bulkin_cb; br->bulk_exc_cb = uftdi_bulkin_cb; br->bulk_client_private = (usb_opaque_t)uf; br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK; rval = usb_pipe_bulk_xfer(uf->uf_bulkin_ph, br, 0); if (rval != USB_SUCCESS) { USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh, "uftdi_rx_start: xfer failed %d", rval); usb_free_bulk_req(br); } mutex_enter(&uf->uf_lock); if (rval != USB_SUCCESS) uf->uf_bulkin_state = UFTDI_PIPE_IDLE; return (rval); }
int usba10_usb_pipe_bulk_xfer( usb_pipe_handle_t pipe_handle, usb_bulk_req_t *reqp, usb_flags_t flags) { return (usb_pipe_bulk_xfer(pipe_handle, reqp, flags)); }
/* * scsa2usb_handle_status_start: * Receive status data */ static int scsa2usb_handle_status_start(scsa2usb_state_t *scsa2usbp, usb_bulk_req_t *req) { int rval; USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, "scsa2usb_handle_status_start: req = 0x%p", (void *)req); ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); /* setup up for receiving CSW */ #ifdef SCSA2USB_BULK_ONLY_TEST req->bulk_attributes = 0; #else req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK; #endif /* SCSA2USB_BULK_ONLY_TEST */ req->bulk_len = CSW_LEN; SCSA2USB_FREE_MSG(req->bulk_data); req->bulk_data = allocb_wait(req->bulk_len, BPRI_LO, STR_NOSIG, NULL); /* Issue the request */ mutex_exit(&scsa2usbp->scsa2usb_mutex); ASSERT(req->bulk_timeout); rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe, req, USB_FLAGS_SLEEP); mutex_enter(&scsa2usbp->scsa2usb_mutex); USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, "scsa2usb_handle_status_start: END rval = 0x%x", rval); if (rval != USB_SUCCESS) { if (scsa2usbp->scsa2usb_pkt_state == SCSA2USB_PKT_PROCESS_CSW) { scsa2usb_bulk_only_reset_recovery(scsa2usbp); return (rval); } if (req->bulk_completion_reason == USB_CR_STALL) { (void) scsa2usb_clear_ept_stall(scsa2usbp, scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress, scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in"); } } return (rval); }
/* * scsa2usb_bulk_only_transport: * Implements the BO state machine by these steps: * a) Issues CBW to a Bulk Only device. * b) Start Data Phase if applicable * c) Start Status Phase * * returns TRAN_* values * * scsa2usb_bulk_only_state_machine: * * scsa2usb_bulk_only_transport() handles the normal transitions or * continuation after clearing stalls or error recovery. * * Command Phase: * prepare a valid CBW and transport it on bulk-out pipe * if error on bulkout: * set pkt_reason to CMD_TRAN_ERR * new pkt state is SCSA2USB_PKT_DO_COMP * reset recovery synchronously * else * proceed to data phase * * Data Phase: * if data in: * setup data in on bulkin * else if data out: * setup data out on bulkout * * data: (in) * copy data transferred so far, no more data to transfer * * if stall on bulkin pipe * terminate data transfers, set cmd_done * clear stall on bulkin syncrhonously * else if other exception * set pkt_reason to CMD_TRAN_ERR * new pkt state is SCSA2USB_PKT_DO_COMP * reset recovery syncrhonously * else (no error) * receive status * * data: (out) * if stall on bulkout pipe * terminate data transfers, set cmd_done * clear stall on bulkout synchronously USBA * else if other exception * set pkt_reason to CMD_TRAN_ERR * new pkt state is SCSA2USB_PKT_DO_COMP * reset recovery synchronously * else (no error) * receive status * * Status Phase: * * if stall (first attempt) * new pkt state is SCSA2USB_PKT_PROCESS_CSW * setup receiving status on bulkin * if stall (second attempt) * new pkt state is SCSA2USB_PKT_DO_COMP * reset recovery synchronously, we are hosed. * else * goto check CSW * else * goto check CSW * * check CSW: * - check length equals 13, signature, and matching tag * - check status is less than or equal to 2 * - check residue is less than or equal to data length * adjust residue based on if we got valid data * * if not OK * new pkt state is SCSA2USB_PKT_DO_COMP * set pkt reason CMD_TRAN_ERR * reset recovery synchronously, we are hosed * else if phase error * new pkt state is SCSA2USB_PKT_DO_COMP * set pkt reason CMD_TRAN_ERR * reset recovery synchronously * else if (status < 2) * if status is equal to 1 * set check condition * if residue * calculate residue from data xferred and DataResidue * * set pkt_residue * goto SCSA2USB_PKT_DO_COMP * * The reset recovery walks sequentially thru device reset, clearing * stalls and pipe resets. When the reset recovery completes we return * to the taskq thread. * * Clearing stalls clears the stall condition, resets the pipe, and * then returns to the transport. */ int scsa2usb_bulk_only_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) { int rval; int nretry; usb_bulk_req_t *req; ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); Cmd_Phase: /* * Start Command Phase * Initialize a bulk_req_t */ req = scsa2usb_init_bulk_req(scsa2usbp, USB_BULK_CBWCMD_LEN, SCSA2USB_BULK_PIPE_TIMEOUT, USB_ATTRS_PIPE_RESET, USB_FLAGS_SLEEP); scsa2usb_fill_in_cbw(scsa2usbp, cmd, req->bulk_data); /* Fill CBW */ SCSA2USB_PRINT_CDB(scsa2usbp, cmd); /* Print CDB */ /* Send a Bulk Command Block Wrapper (CBW) to the device */ mutex_exit(&scsa2usbp->scsa2usb_mutex); ASSERT(req->bulk_timeout); rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, req, USB_FLAGS_SLEEP); mutex_enter(&scsa2usbp->scsa2usb_mutex); USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, "scsa2usb_bulk_only_transport: " "sent cmd = 0x%x Tag = 0x%x DataXferLen = 0x%lx rval = %d", cmd->cmd_cdb[SCSA2USB_OPCODE], cmd->cmd_tag, cmd->cmd_xfercount, rval); if (rval != USB_SUCCESS) { scsa2usb_bulk_only_handle_error(scsa2usbp, req); return (TRAN_FATAL_ERROR); } /* free the data */ SCSA2USB_FREE_MSG(req->bulk_data); req->bulk_data = NULL; Data_Phase: /* * Start Data Phase * re-set timeout */ req->bulk_timeout = scsa2usb_bulk_timeout(cmd->cmd_timeout); /* * we've not transferred any data yet; updated in * scsa2usb_handle_data_done */ cmd->cmd_resid_xfercount = cmd->cmd_xfercount; if (cmd->cmd_xfercount) { /* start I/O to/from the device */ rval = scsa2usb_handle_data_start(scsa2usbp, cmd, req); /* handle data returned, if any */ scsa2usb_handle_data_done(scsa2usbp, cmd, req); if (rval != USB_SUCCESS) { USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, "data xfer phase, error = %d, cr = %d", rval, req->bulk_completion_reason); /* * we ran into an error */ if (req->bulk_completion_reason == USB_CR_STALL) { if (scsa2usbp->scsa2usb_cur_pkt) { scsa2usbp->scsa2usb_cur_pkt-> pkt_reason = CMD_TRAN_ERR; } } else { scsa2usb_bulk_only_handle_error(scsa2usbp, req); return (TRAN_FATAL_ERROR); } } /* end of else */ /* free the data */ SCSA2USB_FREE_MSG(req->bulk_data); req->bulk_data = NULL; } Status_Phase: /* * Start status phase * read in CSW */ for (nretry = 0; nretry < SCSA2USB_STATUS_RETRIES; nretry++) { rval = scsa2usb_handle_status_start(scsa2usbp, req); if ((rval != USB_SUCCESS) && (req->bulk_completion_reason == USB_CR_STALL)) { /* * We ran into STALL condition here. * If the condition cannot be cleared * successfully, retry for limited times. */ scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_PROCESS_CSW; } else { break; } } if (rval == USB_SUCCESS) { /* process CSW */ rval = scsa2usb_handle_csw_result(scsa2usbp, req->bulk_data); } else { scsa2usb_bulk_only_handle_error(scsa2usbp, req); return (TRAN_FATAL_ERROR); } SCSA2USB_FREE_BULK_REQ(req); /* free request */ if ((rval == USB_SUCCESS) && /* CSW was ok */ (scsa2usbp->scsa2usb_cur_pkt->pkt_reason == CMD_CMPLT) && (cmd->cmd_xfercount != 0) && /* more data to xfer */ !cmd->cmd_done) { /* we aren't done yet */ scsa2usb_setup_next_xfer(scsa2usbp, cmd); goto Cmd_Phase; } return (rval == USB_SUCCESS ? TRAN_ACCEPT : TRAN_FATAL_ERROR); }