diff options
Diffstat (limited to 'firmware/usbstack')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 59 |
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 | ||
308 | static void yearday_to_daymonth(int yd, int y, int *d, int *m) | 311 | static 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; |