74static uint32_t usb_stor_transfer_length(SCSI_CMD_T *srb)
103 static char *lengths =
104 "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X"
105 "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH"
106 "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX"
107 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"
108 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"
109 "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX"
110 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX"
111 "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX";
222 if (srb->sc_data_direction == SCSI_DATA_WRITE)
226 switch (lengths[srb->cmnd[0]])
244 len = lengths[srb->cmnd[0]]-
'0';
247 len = (((uint32_t)srb->cmnd[3])<<8) | srb->cmnd[4];
250 len = (((uint32_t)srb->cmnd[7])<<8) | srb->cmnd[8];
253 len = (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
256 len = (((uint32_t)srb->cmnd[2])<<16) |
257 (((uint32_t)srb->cmnd[3])<<8) | srb->cmnd[4];
260 len = (((uint32_t)srb->cmnd[3])<<16) |
261 (((uint32_t)srb->cmnd[4])<<8) | srb->cmnd[5];
264 len = (((uint32_t)srb->cmnd[6])<<16) |
265 (((uint32_t)srb->cmnd[7])<<8) | srb->cmnd[8];
268 len = (((uint32_t)srb->cmnd[7])<<16) |
269 (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
272 len = (((uint32_t)srb->cmnd[2])<<24) |
273 (((uint32_t)srb->cmnd[3])<<16) |
274 (((uint32_t)srb->cmnd[4])<<8) | srb->cmnd[5];
277 len = (((uint32_t)srb->cmnd[6])<<24) |
278 (((uint32_t)srb->cmnd[7])<<16) |
279 (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
292 UMAS_DEBUG(
"Error: UNSUPPORTED COMMAND %02X\n", srb->cmnd[0]);
300 UMAS_DEBUG(
"Error: COMMAND %02X out of range or table inconsistent (%c).\n",
301 srb->cmnd[0], lengths[srb->cmnd[0]] );
312 sg = (SCATTER_LIST_T *) srb->request_buff;
313 for (i=0; i<srb->use_sg; i++)
314 total += sg[i].length;
319 len = srb->request_bufflen;
330static int clear_halt(
USB_DEV_T *dev,
int pipe)
333 int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
335 UMAS_DEBUG(
"clear_halt!\n");
337 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
342 UMAS_DEBUG(
"clear_halt failed!!\n");
347 usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
348 usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0x1000);
354volatile static int _UmasUrbComplete;
356int is_urb_completed(
void)
358 return _UmasUrbComplete;
368static void usb_stor_blocking_completion(
URB_T *urb)
370 _UmasUrbComplete = 1;
372#ifdef CONFIG_USB_STORAGE_DEBUG
373 UMAS_DEBUG(
"usb_stor_blocking_completion called...\n");
383static int usb_stor_control_msg(UMAS_DATA_T *umas, uint32_t pipe,
384 uint8_t request, uint8_t requesttype, uint16_t
value,
385 uint16_t index,
void *data, uint16_t size)
387 URB_T *urb = umas->current_urb;
393 dr.requesttype = requesttype;
394 dr.request = request;
400 FILL_CONTROL_URB(urb, umas->pusb_dev, pipe, (uint8_t *)&dr, data, size,
401 usb_stor_blocking_completion,
NULL);
406 _UmasUrbComplete = 0;
415 for (t0 = 0; t0 < 0x8000000; t0++)
417 if (is_urb_completed())
422 t0 = umas_get_ticks();
423 while (umas_get_ticks() - t0 < 300)
425 if (is_urb_completed())
429 if (umas_get_ticks() - t0 >= 300)
432 UMAS_DEBUG(
"usb_stor_control_msg time-out failed!\n");
449static int usb_stor_bulk_msg(UMAS_DATA_T *umas,
void *data,
int pipe,
450 uint32_t len, uint32_t *act_len)
452 URB_T *urb = umas->current_urb;
457 FILL_BULK_URB(urb, umas->pusb_dev, pipe, data, len,
458 usb_stor_blocking_completion,
NULL);
463 _UmasUrbComplete = 0;
471 for (t0 = 0; t0 < 0x1000000; t0++)
473 if (is_urb_completed())
478 t0 = umas_get_ticks();
479 while (umas_get_ticks() - t0 < 500)
481 if (is_urb_completed())
484 if (umas_get_ticks() - t0 >= 500)
487 UMAS_DEBUG(
"usb_stor_bulk_msg time-out failed!\n");
510static int usb_stor_transfer_partial(UMAS_DATA_T *umas,
char *buf,
int length)
517 if (umas->srb.sc_data_direction == SCSI_DATA_READ)
518 pipe = usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in);
520 pipe = usb_sndbulkpipe(umas->pusb_dev, umas->ep_out);
523 UMAS_VDEBUG(
"usb_stor_transfer_partial - xfer %d bytes\n", length);
524 result = usb_stor_bulk_msg(umas, buf, pipe, length, &partial);
525 UMAS_VDEBUG(
"usb_stor_bulk_msg() returned %d xferred %d/%d\n", result, partial, length);
531 UMAS_DEBUG(
"usb_stor_transfer_partial - clearing endpoint halt for pipe 0x%x\n", pipe);
532 clear_halt(umas->pusb_dev, pipe);
536 if (partial == length)
538 UMAS_VDEBUG(
"usb_stor_transfer_partial - transfer complete\n");
539 return UMAS_BULK_TRANSFER_GOOD;
548 UMAS_DEBUG(
"usb_stor_transfer_partial - device NAKed\n");
549 return UMAS_BULK_TRANSFER_FAILED;
555 UMAS_DEBUG(
"usb_stor_transfer_partial - transfer aborted\n");
556 return UMAS_BULK_TRANSFER_ABORTED;
560 UMAS_DEBUG(
"usb_stor_transfer_partial - unknown error\n");
561 return UMAS_BULK_TRANSFER_FAILED;
565 return UMAS_BULK_TRANSFER_SHORT;
577static void us_transfer(SCSI_CMD_T *srb, UMAS_DATA_T* umas)
581 uint32_t total_transferred = 0;
582 uint32_t transfer_amount;
586 transfer_amount = usb_stor_transfer_length(srb);
589 if (transfer_amount > srb->request_bufflen)
590 transfer_amount = srb->request_bufflen;
599 sg = (SCATTER_LIST_T *) srb->request_buff;
600 for (i = 0; i < srb->use_sg; i++)
603 if (transfer_amount - total_transferred >= sg[i].length)
605 result = usb_stor_transfer_partial(umas, sg[i].address, sg[i].length);
606 total_transferred += sg[i].length;
609 result = usb_stor_transfer_partial(umas, sg[i].address,
610 transfer_amount - total_transferred);
617 result = usb_stor_transfer_partial(umas, (
char *)srb->request_buff, transfer_amount);
620 srb->result = result;
635void UMAS_InvokeTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
641 result = umas->transport(srb, umas);
647 if (result == USB_STOR_TRANSPORT_ABORTED)
649 UMAS_DEBUG(
"UMAS_InvokeTransport - transport indicates command was aborted\n");
650 srb->result = DID_ABORT << 16;
667 if ((umas->protocol == UMAS_PR_CB) || (umas->protocol == UMAS_PR_DPCM_USB))
669 UMAS_VDEBUG(
"UMAS_InvokeTransport - CB transport device requiring auto-sense\n");
677 if ((umas->subclass == UMAS_SC_UFI) &&
678 ((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY)))
680 UMAS_DEBUG(
"UMAS_InvokeTransport - no auto-sense for a special command\n");
690 if (result == USB_STOR_TRANSPORT_FAILED)
692 UMAS_VDEBUG(
"UMAS_InvokeTransport - transport indicates command failure\n");
695 if (result == USB_STOR_TRANSPORT_ERROR)
698 umas->transport_reset(umas);
699 UMAS_DEBUG(
"UMAS_InvokeTransport - transport indicates transport error\n");
702 srb->result = DID_ERROR << 16;
710 if ((srb->result == UMAS_BULK_TRANSFER_SHORT) &&
711 !((srb->cmnd[0] == REQUEST_SENSE) ||
712 (srb->cmnd[0] == INQUIRY) ||
713 (srb->cmnd[0] == MODE_SENSE) ||
714 (srb->cmnd[0] == LOG_SENSE) ||
715 (srb->cmnd[0] == MODE_SENSE_10)))
717 UMAS_DEBUG(
"UMAS_InvokeTransport - unexpectedly short transfer\n");
725 void *old_request_buffer;
727 uint32_t old_request_bufflen;
728 uint8_t old_sc_data_direction;
729 uint8_t old_cmnd[MAX_COMMAND_SIZE];
731 UMAS_VDEBUG(
"UMAS_InvokeTransport - Issuing auto-REQUEST_SENSE\n");
734 memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
737 srb->cmnd[0] = REQUEST_SENSE;
738 srb->cmnd[1] = old_cmnd[1] & 0xE0;
745 old_sc_data_direction = srb->sc_data_direction;
746 srb->sc_data_direction = SCSI_DATA_READ;
749 old_request_buffer = srb->request_buff;
750 srb->request_buff = srb->sense_buffer;
753 old_request_bufflen = srb->request_bufflen;
754 srb->request_bufflen = 18;
757 old_sg = srb->use_sg;
761 temp_result = umas->transport(&umas->srb, umas);
762 if (temp_result != USB_STOR_TRANSPORT_GOOD)
764 UMAS_DEBUG(
"-- auto-sense failure\n");
771 if (!(umas->flags & UMAS_FL_SCM_MULT_TARG))
773 umas->transport_reset(umas);
775 srb->result = DID_ERROR << 16;
779 UMAS_VDEBUG(
"-- Result from auto-sense is %d\n", temp_result);
780 UMAS_VDEBUG(
"-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
781 srb->sense_buffer[0], srb->sense_buffer[2] & 0xf,
782 srb->sense_buffer[12], srb->sense_buffer[13]);
785 srb->result = CHECK_CONDITION << 1;
788 srb->request_buff = old_request_buffer;
789 srb->request_bufflen = old_request_bufflen;
790 srb->use_sg = old_sg;
791 srb->sc_data_direction = old_sc_data_direction;
792 memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
795 if ((srb->sense_buffer[2] & 0xf) == 0x0)
796 srb->result = GOOD << 1;
799 srb->result = GOOD << 1;
805 if (result == USB_STOR_TRANSPORT_FAILED)
806 srb->result = CHECK_CONDITION << 1;
813 if ((umas->protocol == UMAS_PR_CB || umas->protocol == UMAS_PR_DPCM_USB) &&
814 (result == USB_STOR_TRANSPORT_GOOD) && ((srb->sense_buffer[2] & 0xf) == 0x0))
815 srb->sense_buffer[0] = 0x0;
825void UMAS_CbiIrq(
URB_T *urb)
827 UMAS_DATA_T *umas = (UMAS_DATA_T *)urb->
context;
832 UMAS_DEBUG(
"-- IRQ too short\n");
839 UMAS_DEBUG(
"-- device has been removed\n");
844 if (umas->irqbuf[0] && (umas->subclass != UMAS_SC_UFI))
846 UMAS_DEBUG(
"-- not a command-completion IRQ\n");
852 if (!umas->ip_wanted)
854 UMAS_DEBUG(
"ERROR: Unwanted interrupt received!\n");
858 umas->ip_wanted = 0 ;
861 umas->irqdata[0] = umas->irqbuf[0];
862 umas->irqdata[1] = umas->irqbuf[1];
867int UMAS_CbiTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
879 result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev,0),
881 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
882 umas->ifnum, srb->cmnd, srb->cmd_len);
885 UMAS_VDEBUG(
"Call to usb_stor_control_msg() returned %d\n", result);
890 return USB_STOR_TRANSPORT_ABORTED;
895 UMAS_VDEBUG(
"-- Stall on control pipe. Clearing\n");
896 result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0));
897 UMAS_VDEBUG(
"-- clear_halt() returns %d\n", result);
898 return USB_STOR_TRANSPORT_FAILED;
902 return USB_STOR_TRANSPORT_ERROR;
907 if (usb_stor_transfer_length(srb))
909 us_transfer(srb, umas);
910 UMAS_VDEBUG(
"CBI data stage result is 0x%x\n", srb->result);
913 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
914 return USB_STOR_TRANSPORT_ABORTED;
925 UMAS_DEBUG(
"Did not get interrupt on CBI\n");
927 return USB_STOR_TRANSPORT_ABORTED;
930 UMAS_VDEBUG(
"Got interrupt data (0x%x, 0x%x)\n", umas->irqdata[0], umas->irqdata[1]);
940 if (umas->subclass == UMAS_SC_UFI)
942 if ((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY))
943 return USB_STOR_TRANSPORT_GOOD;
946 if (((uint8_t*)umas->irq_urb->transfer_buffer)[0])
947 return USB_STOR_TRANSPORT_FAILED;
949 return USB_STOR_TRANSPORT_GOOD;
958 if (umas->irqdata[0])
960 UMAS_VDEBUG(
"CBI IRQ data showed reserved bType %d\n", umas->irqdata[0]);
961 return USB_STOR_TRANSPORT_ERROR;
964 switch (umas->irqdata[1] & 0x0F)
967 return USB_STOR_TRANSPORT_GOOD;
969 return USB_STOR_TRANSPORT_FAILED;
971 return USB_STOR_TRANSPORT_ERROR;
980int UMAS_CbTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
986 result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev,0),
988 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
989 umas->ifnum, srb->cmnd, srb->cmd_len);
992 UMAS_VDEBUG(
"UMAS_CbTransport - Call to usb_stor_control_msg() returned %d\n", result);
997 return USB_STOR_TRANSPORT_ABORTED;
1002 UMAS_DEBUG(
"UMAS_CbTransport - Stall on control pipe. Clearing\n");
1003 result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0));
1004 UMAS_DEBUG(
"UMAS_CbTransport - clear_halt() returns %d\n", result);
1005 return USB_STOR_TRANSPORT_FAILED;
1009 return USB_STOR_TRANSPORT_ERROR;
1014 if (usb_stor_transfer_length(srb))
1016 us_transfer(srb, umas);
1017 UMAS_VDEBUG(
"UMAS_CbTransport - CB data stage result is 0x%x\n", srb->result);
1020 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
1021 return USB_STOR_TRANSPORT_ABORTED;
1028 return USB_STOR_TRANSPORT_GOOD;
1038int UMAS_BulkMaxLun(UMAS_DATA_T *umas)
1043 uint8_t dma_buff[4];
1046 pipe = usb_rcvctrlpipe(umas->pusb_dev, 0);
1048 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1049 0, umas->ifnum, dma_buff, 1, 0);
1053 UMAS_DEBUG(
"GetMaxLUN command result is %d, data is %d\n", result, data);
1062 UMAS_DEBUG(
"clearing endpoint halt for pipe 0x%x\n", pipe);
1063 clear_halt(umas->pusb_dev, pipe);
1072int UMAS_BulkTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
1074 int result, status = 0;
1077 struct bulk_cb_wrap bcb;
1078 struct bulk_cs_wrap bcs;
1081 if (!umas->pusb_dev)
1085 bcb.Signature = UMAS_BULK_CB_SIGN;
1086 bcb.DataTransferLength = usb_stor_transfer_length(srb);
1087 bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
1088 bcb.Tag = srb->serial_number;
1089 bcb.Lun = srb->cmnd[1] >> 5;
1091 if (umas->flags & UMAS_FL_SCM_MULT_TARG)
1092 bcb.Lun |= srb->target << 4;
1093 bcb.Length = srb->cmd_len;
1096 pipe = usb_sndbulkpipe(umas->pusb_dev, umas->ep_out);
1099 memset(bcb.CDB, 0,
sizeof(bcb.CDB));
1100 memcpy(bcb.CDB, srb->cmnd, bcb.Length);
1103 UMAS_VDEBUG(
"Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
1104 bcb.Signature, bcb.Tag, (bcb.Lun >> 4), (bcb.Lun & 0x0F),
1105 bcb.DataTransferLength, bcb.Flags, bcb.Length);
1106 result = usb_stor_bulk_msg(umas, &bcb, pipe, UMAS_BULK_CB_WRAP_LEN, &partial);
1107 UMAS_VDEBUG(
"Bulk command transfer result=%d\n", result);
1111 return USB_STOR_TRANSPORT_ABORTED;
1116 UMAS_DEBUG(
"UMAS_BulkTransport - 1 clearing endpoint halt for pipe 0x%x\n", pipe);
1117 clear_halt(umas->pusb_dev, pipe);
1122 status = USB_STOR_TRANSPORT_ERROR;
1130 if (bcb.DataTransferLength)
1132 us_transfer(srb, umas);
1135 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
1137 status = USB_STOR_TRANSPORT_ABORTED;
1149 pipe = usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in);
1152 UMAS_VDEBUG(
"Attempting to get CSW...\n");
1153 result = usb_stor_bulk_msg(umas, (
char *)&bcs, pipe, UMAS_BULK_CS_WRAP_LEN, &partial);
1158 status = USB_STOR_TRANSPORT_ABORTED;
1165 UMAS_DEBUG(
"get CSW failed - clearing endpoint halt for pipe 0x%x\n", pipe);
1166 clear_halt(umas->pusb_dev, pipe);
1169 UMAS_DEBUG(
"Attempting to get CSW (2nd try)...\n");
1170 result = usb_stor_bulk_msg(umas, &bcs, pipe, UMAS_BULK_CS_WRAP_LEN, &partial);
1175 UMAS_DEBUG(
"get CSW Command was aborted!\n");
1176 status = USB_STOR_TRANSPORT_ABORTED;
1183 UMAS_DEBUG(
"get CSW command 2nd try failed - clearing halt for pipe 0x%x\n", pipe);
1184 clear_halt(umas->pusb_dev, pipe);
1185 status = USB_STOR_TRANSPORT_ERROR;
1191 UMAS_VDEBUG(
"Bulk status result = %d\n", result);
1194 status = USB_STOR_TRANSPORT_ERROR;
1199 UMAS_VDEBUG(
"Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
1200 USB_SWAP32(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status);
1201 if ((bcs.Signature != UMAS_BULK_CS_SIGN) || (bcs.Tag != bcb.Tag) ||
1202 (bcs.Status > UMAS_BULK_STAT_PHASE) || (partial != 13))
1204 UMAS_DEBUG(
"Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
1205 USB_SWAP32(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status);
1206 status = USB_STOR_TRANSPORT_ERROR;
1213 case UMAS_BULK_STAT_OK:
1215 return USB_STOR_TRANSPORT_GOOD;
1217 case UMAS_BULK_STAT_FAIL:
1219 status = USB_STOR_TRANSPORT_FAILED;
1222 case UMAS_BULK_STAT_PHASE:
1226 status = USB_STOR_TRANSPORT_ERROR;
1245int UMAS_CbReset(UMAS_DATA_T *umas)
1251 if (!umas->pusb_dev)
1254 memset(cmd, 0xFF,
sizeof(cmd));
1255 cmd[0] = SEND_DIAGNOSTIC;
1257 result =
USBH_SendCtrlMsg(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev,0),
1258 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1259 0, umas->ifnum, cmd,
sizeof(cmd), 0);
1262 UMAS_DEBUG(
"UMAS_CbReset - CB[I] soft reset failed %d\n", result);
1266 UMAS_VDEBUG(
"UMAS_CbReset - clearing endpoint halt\n");
1267 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in));
1268 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_out));
1270 UMAS_VDEBUG(
"UMAS_CbReset - done\n");
1281int UMAS_BulkReset(UMAS_DATA_T *umas)
1285 UMAS_VDEBUG(
"Bulk reset requested\n");
1286 printf(
"UMAS_BulkReset!\n");
1289 if (!umas->pusb_dev)
1293 usb_sndctrlpipe(umas->pusb_dev,0), UMAS_BULK_RESET_REQUEST,
1294 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, umas->ifnum,
1298 UMAS_DEBUG(
"Bulk soft reset failed %d\n", result);
1302 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in));
1303 clear_halt(umas->pusb_dev, usb_sndbulkpipe(umas->pusb_dev, umas->ep_out));
1305 UMAS_VDEBUG(
"Bulk soft reset completed\n");
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
int32_t USBH_SubmitUrb(URB_T *urb)
Submit an URB to USB core for transfer data.
int32_t USBH_SendCtrlMsg(USB_DEV_T *dev, uint32_t pipe, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, void *data, uint16_t size, int timeout)
Execute a control transfer.
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
#define NULL
NULL pointer.
USB Host core driver header file.