summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/usbstack/usb_storage.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 647fbd8e5b..3373bf41f3 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -63,6 +63,8 @@
63#define READ_BUFFER_SIZE (1024*64) 63#define READ_BUFFER_SIZE (1024*64)
64#endif 64#endif
65 65
66#define MAX_CBW_SIZE 1024
67
66#ifdef USB_WRITE_BUFFER_SIZE 68#ifdef USB_WRITE_BUFFER_SIZE
67#define WRITE_BUFFER_SIZE USB_WRITE_BUFFER_SIZE 69#define WRITE_BUFFER_SIZE USB_WRITE_BUFFER_SIZE
68#else 70#else
@@ -302,7 +304,8 @@ static enum {
302 SENDING_FAILED_RESULT, 304 SENDING_FAILED_RESULT,
303 RECEIVING_BLOCKS, 305 RECEIVING_BLOCKS,
304 RECEIVING_TIME, 306 RECEIVING_TIME,
305 SENDING_CSW 307 WAITING_FOR_CSW_COMPLETION_OR_COMMAND,
308 WAITING_FOR_CSW_COMPLETION
306} state = WAITING_FOR_COMMAND; 309} state = WAITING_FOR_COMMAND;
307 310
308static void yearday_to_daymonth(int yd, int y, int *d, int *m) 311static void yearday_to_daymonth(int yd, int y, int *d, int *m)
@@ -447,7 +450,7 @@ void usb_storage_init_connection(void)
447 450
448#if CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \ 451#if CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
449 defined(BOOTLOADER) || CONFIG_CPU == DM320 452 defined(BOOTLOADER) || CONFIG_CPU == DM320
450 static unsigned char _cbw_buffer[ALLOCATE_BUFFER_SIZE] 453 static unsigned char _cbw_buffer[MAX_CBW_SIZE]
451 USB_DEVBSS_ATTR __attribute__((aligned(32))); 454 USB_DEVBSS_ATTR __attribute__((aligned(32)));
452 cbw_buffer = (void *)_cbw_buffer; 455 cbw_buffer = (void *)_cbw_buffer;
453 456
@@ -469,13 +472,13 @@ void usb_storage_init_connection(void)
469#else 472#else
470 cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0); 473 cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0);
471#endif 474#endif
472 tb.transfer_buffer = cbw_buffer + 1024; 475 tb.transfer_buffer = cbw_buffer + MAX_CBW_SIZE;
473 cpucache_invalidate(); 476 cpucache_invalidate();
474#ifdef USB_USE_RAMDISK 477#ifdef USB_USE_RAMDISK
475 ramdisk_buffer = tb.transfer_buffer + ALLOCATE_BUFFER_SIZE; 478 ramdisk_buffer = tb.transfer_buffer + ALLOCATE_BUFFER_SIZE;
476#endif 479#endif
477#endif 480#endif
478 usb_drv_recv(ep_out, cbw_buffer, 1024); 481 usb_drv_recv(ep_out, cbw_buffer, MAX_CBW_SIZE);
479 482
480 int i; 483 int i;
481 for(i=0;i<storage_num_drives();i++) { 484 for(i=0;i<storage_num_drives();i++) {
@@ -569,27 +572,30 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
569 cur_sense_data.ascq=0; 572 cur_sense_data.ascq=0;
570 } 573 }
571 break; 574 break;
572 case WAITING_FOR_COMMAND: 575 case WAITING_FOR_CSW_COMPLETION_OR_COMMAND:
573 if(dir==USB_DIR_IN) { 576 if(dir==USB_DIR_IN) {
574 logf("IN received in WAITING_FOR_COMMAND"); 577 /* This was the CSW */
575 } 578 state = WAITING_FOR_COMMAND;
576 //logf("command received");
577 if(letoh32(cbw->signature) == CBW_SIGNATURE) {
578 handle_scsi(cbw);
579 } 579 }
580 else { 580 else {
581 usb_drv_stall(ep_in, true,true); 581 /* This was the command */
582 usb_drv_stall(ep_out, true,false); 582 state = WAITING_FOR_CSW_COMPLETION;
583 /* We now have the CBW, but we won't execute it yet to avoid
584 * issues with the still-pending CSW */
583 } 585 }
584 break; 586 break;
585 case SENDING_CSW: 587 case WAITING_FOR_COMMAND:
588 if(dir==USB_DIR_IN) {
589 logf("IN received in WAITING_FOR_COMMAND");
590 }
591 handle_scsi(cbw);
592 break;
593 case WAITING_FOR_CSW_COMPLETION:
586 if(dir==USB_DIR_OUT) { 594 if(dir==USB_DIR_OUT) {
587 logf("OUT received in SENDING_CSW"); 595 logf("OUT received in WAITING_FOR_CSW_COMPLETION");
588 } 596 }
589 //logf("csw sent, now go back to idle"); 597 handle_scsi(cbw);
590 state = WAITING_FOR_COMMAND; 598 break;
591 /* Already start waiting for the next command */
592 usb_drv_recv(ep_out, cbw_buffer, 1024);
593#if 0 599#if 0
594 if(cur_cmd.cur_cmd == SCSI_WRITE_10) 600 if(cur_cmd.cur_cmd == SCSI_WRITE_10)
595 { 601 {
@@ -747,6 +753,17 @@ static void handle_scsi(struct command_block_wrapper* cbw)
747 bool lun_present=true; 753 bool lun_present=true;
748 unsigned char lun = cbw->lun; 754 unsigned char lun = cbw->lun;
749 unsigned int block_size_mult = 1; 755 unsigned int block_size_mult = 1;
756
757 if(letoh32(cbw->signature) != CBW_SIGNATURE) {
758 usb_drv_stall(ep_in, true,true);
759 usb_drv_stall(ep_out, true,false);
760 return;
761 }
762 /* Clear the signature to prevent possible bugs elsewhere
763 * to trigger a second execution of the same command with
764 * bogus data */
765 cbw->signature=0;
766
750#ifdef HIDE_FIRST_DRIVE 767#ifdef HIDE_FIRST_DRIVE
751 lun++; 768 lun++;
752#endif 769#endif
@@ -1186,8 +1203,12 @@ static void send_csw(int status)
1186 1203
1187 usb_drv_send_nonblocking(ep_in, tb.csw, 1204 usb_drv_send_nonblocking(ep_in, tb.csw,
1188 sizeof(struct command_status_wrapper)); 1205 sizeof(struct command_status_wrapper));
1189 state = SENDING_CSW; 1206 state = WAITING_FOR_CSW_COMPLETION_OR_COMMAND;
1190 //logf("CSW: %X",status); 1207 //logf("CSW: %X",status);
1208 /* Already start waiting for the next command */
1209 usb_drv_recv(ep_out, cbw_buffer, MAX_CBW_SIZE);
1210 /* The next completed transfer will be either the CSW one
1211 * or the new command */
1191 1212
1192 if(status == UMS_STATUS_GOOD) { 1213 if(status == UMS_STATUS_GOOD) {
1193 cur_sense_data.sense_key=0; 1214 cur_sense_data.sense_key=0;