diff options
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 59 |
1 files changed, 23 insertions, 36 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index 005697f6fa..1ff3b1ec4c 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "usb_storage.h" | 32 | #include "usb_storage.h" |
33 | #include "timefuncs.h" | 33 | #include "timefuncs.h" |
34 | 34 | ||
35 | /* For sector filter macro definitions */ | ||
36 | #include "usb-target.h" | ||
35 | 37 | ||
36 | /* Enable the following define to export only the SD card slot. This | 38 | /* Enable the following define to export only the SD card slot. This |
37 | * is useful for USBCV MSC tests, as those are destructive. | 39 | * is useful for USBCV MSC tests, as those are destructive. |
@@ -47,6 +49,15 @@ | |||
47 | #define SECTOR_SIZE 512 | 49 | #define SECTOR_SIZE 512 |
48 | #endif | 50 | #endif |
49 | 51 | ||
52 | /* These defaults allow the operation */ | ||
53 | #ifndef USBSTOR_READ_SECTORS_FILTER | ||
54 | #define USBSTOR_READ_SECTORS_FILTER() ({ 0; }) | ||
55 | #endif | ||
56 | |||
57 | #ifndef USBSTOR_WRITE_SECTORS_FILTER | ||
58 | #define USBSTOR_WRITE_SECTORS_FILTER() ({ 0; }) | ||
59 | #endif | ||
60 | |||
50 | /* the ARC driver currently supports up to 64k USB transfers. This is | 61 | /* the ARC driver currently supports up to 64k USB transfers. This is |
51 | * enough for efficient mass storage support, as commonly host OSes | 62 | * enough for efficient mass storage support, as commonly host OSes |
52 | * don't do larger SCSI transfers anyway, so larger USB transfers | 63 | * don't do larger SCSI transfers anyway, so larger USB transfers |
@@ -342,23 +353,6 @@ static void yearday_to_daymonth(int yd, int y, int *d, int *m) | |||
342 | *m = i; | 353 | *m = i; |
343 | } | 354 | } |
344 | 355 | ||
345 | #ifdef TOSHIBA_GIGABEAT_S | ||
346 | |||
347 | /* The Gigabeat S factory partition table contains invalid values for the | ||
348 | "active" flag in the MBR. This prevents at least the Linux kernel from | ||
349 | accepting the partition table, so we fix it on-the-fly. */ | ||
350 | |||
351 | static void fix_mbr(unsigned char* mbr) | ||
352 | { | ||
353 | unsigned char* p = mbr + 0x1be; | ||
354 | |||
355 | p[0x00] &= 0x80; | ||
356 | p[0x10] &= 0x80; | ||
357 | p[0x20] &= 0x80; | ||
358 | p[0x30] &= 0x80; | ||
359 | } | ||
360 | #endif | ||
361 | |||
362 | static bool check_disk_present(IF_MD_NONVOID(int volume)) | 356 | static bool check_disk_present(IF_MD_NONVOID(int volume)) |
363 | { | 357 | { |
364 | #ifdef USB_USE_RAMDISK | 358 | #ifdef USB_USE_RAMDISK |
@@ -491,14 +485,7 @@ void usb_storage_init_connection(void) | |||
491 | 485 | ||
492 | int i; | 486 | int i; |
493 | for(i=0;i<storage_num_drives();i++) { | 487 | for(i=0;i<storage_num_drives();i++) { |
494 | #ifdef TOSHIBA_GIGABEAT_S | ||
495 | /* As long as the Gigabeat S is a non-removable device, we need | ||
496 | to mark the device as locked to avoid usb_storage_try_release_ata() | ||
497 | to leave MSC mode while the device is in use */ | ||
498 | locked[i] = true; | ||
499 | #else | ||
500 | locked[i] = false; | 488 | locked[i] = false; |
501 | #endif | ||
502 | ejected[i] = !check_disk_present(IF_MD(i)); | 489 | ejected[i] = !check_disk_present(IF_MD(i)); |
503 | queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); | 490 | queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); |
504 | } | 491 | } |
@@ -549,10 +536,15 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length) | |||
549 | cur_cmd.data[cur_cmd.data_select], | 536 | cur_cmd.data[cur_cmd.data_select], |
550 | MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); | 537 | MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); |
551 | #else | 538 | #else |
552 | int result = storage_write_sectors(IF_MD2(cur_cmd.lun,) | 539 | int result = USBSTOR_WRITE_SECTORS_FILTER(); |
540 | |||
541 | if (result == 0) { | ||
542 | result = storage_write_sectors(IF_MD2(cur_cmd.lun,) | ||
553 | cur_cmd.sector, | 543 | cur_cmd.sector, |
554 | MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), | 544 | MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), |
555 | cur_cmd.data[cur_cmd.data_select]); | 545 | cur_cmd.data[cur_cmd.data_select]); |
546 | } | ||
547 | |||
556 | if(result != 0) { | 548 | if(result != 0) { |
557 | send_csw(UMS_STATUS_FAIL); | 549 | send_csw(UMS_STATUS_FAIL); |
558 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; | 550 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; |
@@ -725,6 +717,11 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* des | |||
725 | 717 | ||
726 | static void send_and_read_next(void) | 718 | static void send_and_read_next(void) |
727 | { | 719 | { |
720 | int result = USBSTOR_READ_SECTORS_FILTER(); | ||
721 | |||
722 | if(result != 0 && cur_cmd.last_result == 0) | ||
723 | cur_cmd.last_result = result; | ||
724 | |||
728 | send_block_data(cur_cmd.data[cur_cmd.data_select], | 725 | send_block_data(cur_cmd.data[cur_cmd.data_select], |
729 | MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); | 726 | MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); |
730 | 727 | ||
@@ -742,7 +739,7 @@ static void send_and_read_next(void) | |||
742 | ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, | 739 | ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, |
743 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); | 740 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); |
744 | #else | 741 | #else |
745 | int result = storage_read_sectors(IF_MD2(cur_cmd.lun,) | 742 | result = storage_read_sectors(IF_MD2(cur_cmd.lun,) |
746 | cur_cmd.sector, | 743 | cur_cmd.sector, |
747 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), | 744 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), |
748 | cur_cmd.data[cur_cmd.data_select]); | 745 | cur_cmd.data[cur_cmd.data_select]); |
@@ -1104,12 +1101,6 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
1104 | cur_cmd.sector, | 1101 | cur_cmd.sector, |
1105 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), | 1102 | MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), |
1106 | cur_cmd.data[cur_cmd.data_select]); | 1103 | cur_cmd.data[cur_cmd.data_select]); |
1107 | |||
1108 | #ifdef TOSHIBA_GIGABEAT_S | ||
1109 | if(cur_cmd.sector == 0) { | ||
1110 | fix_mbr(cur_cmd.data[cur_cmd.data_select]); | ||
1111 | } | ||
1112 | #endif | ||
1113 | #endif | 1104 | #endif |
1114 | send_and_read_next(); | 1105 | send_and_read_next(); |
1115 | } | 1106 | } |
@@ -1262,9 +1253,5 @@ static void fill_inquiry(IF_MD_NONVOID(int lun)) | |||
1262 | tb.inquiry->Versions = 4; /* SPC-2 */ | 1253 | tb.inquiry->Versions = 4; /* SPC-2 */ |
1263 | tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ | 1254 | tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ |
1264 | 1255 | ||
1265 | #ifdef TOSHIBA_GIGABEAT_S | ||
1266 | tb.inquiry->DeviceTypeModifier = 0; | ||
1267 | #else | ||
1268 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | 1256 | tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; |
1269 | #endif | ||
1270 | } | 1257 | } |