summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_storage.c
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-11-01 16:14:28 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-11-01 16:14:28 +0000
commit2f8a0081c64534da23fc0fa9cc685eb7454fd9c9 (patch)
tree84dbdbd5326cb48f43d2ebd5a4c86e992c1d5288 /firmware/usbstack/usb_storage.c
parent646cac0bde7b11fa7bcb670d1d76eec78e360485 (diff)
downloadrockbox-2f8a0081c64534da23fc0fa9cc685eb7454fd9c9.tar.gz
rockbox-2f8a0081c64534da23fc0fa9cc685eb7454fd9c9.zip
Apply FS#9500. This adds a storage_*() abstraction to replace ata_*(). To do that, it also introduces sd_*, nand_*, and mmc_*.
This should be a good first step to allow multi-driver targets, like the Elio (ATA/SD), or the D2 (NAND/SD). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18960 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r--firmware/usbstack/usb_storage.c125
1 files changed, 49 insertions, 76 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 198ff46a56..24ac00138d 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -24,7 +24,7 @@
24#include "usb_drv.h" 24#include "usb_drv.h"
25//#define LOGF_ENABLE 25//#define LOGF_ENABLE
26#include "logf.h" 26#include "logf.h"
27#include "ata.h" 27#include "storage.h"
28#include "hotswap.h" 28#include "hotswap.h"
29#include "disk.h" 29#include "disk.h"
30/* Needed to get at the audio buffer */ 30/* Needed to get at the audio buffer */
@@ -36,7 +36,7 @@
36 36
37/* The SD card driver on Sansa c200 and e200 can cause write corruption, 37/* The SD card driver on Sansa c200 and e200 can cause write corruption,
38 * often triggered by simultaneous USB activity. This can be largely avoided 38 * often triggered by simultaneous USB activity. This can be largely avoided
39 * by not overlapping ata_write_sector() with USB transfers. This does reduce 39 * by not overlapping storage_write_sector() with USB transfers. This does reduce
40 * write performance, so we only do it for the affected DAPs 40 * write performance, so we only do it for the affected DAPs
41 */ 41 */
42#if (CONFIG_STORAGE & STORAGE_SD) 42#if (CONFIG_STORAGE & STORAGE_SD)
@@ -147,10 +147,8 @@ struct inquiry_data {
147struct report_lun_data { 147struct report_lun_data {
148 unsigned int lun_list_length; 148 unsigned int lun_list_length;
149 unsigned int reserved1; 149 unsigned int reserved1;
150 unsigned char lun0[8]; 150 // TODO this should be cleaned up with the VOLUMES vs DRIVES mess
151#ifdef HAVE_HOTSWAP 151 unsigned char luns[NUM_VOLUMES][8];
152 unsigned char lun1[8];
153#endif
154} __attribute__ ((packed)); 152} __attribute__ ((packed));
155 153
156struct sense_data { 154struct sense_data {
@@ -263,7 +261,7 @@ static void send_command_result(void *data,int size);
263static void send_command_failed_result(void); 261static void send_command_failed_result(void);
264static void send_block_data(void *data,int size); 262static void send_block_data(void *data,int size);
265static void receive_block_data(void *data,int size); 263static void receive_block_data(void *data,int size);
266static void identify2inquiry(int lun); 264static void fill_inquiry(IF_MV_NONVOID(int lun));
267static void send_and_read_next(void); 265static void send_and_read_next(void);
268static bool ejected[NUM_VOLUMES]; 266static bool ejected[NUM_VOLUMES];
269 267
@@ -289,7 +287,7 @@ static bool check_disk_present(IF_MV_NONVOID(int volume))
289 return true; 287 return true;
290#else 288#else
291 unsigned char sector[512]; 289 unsigned char sector[512];
292 return ata_read_sectors(IF_MV2(volume,)0,1,sector) == 0; 290 return storage_read_sectors(IF_MV2(volume,)0,1,sector) == 0;
293#endif 291#endif
294} 292}
295 293
@@ -460,7 +458,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
460 cur_cmd.data[cur_cmd.data_select], 458 cur_cmd.data[cur_cmd.data_select],
461 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 459 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
462#else 460#else
463 int result = ata_write_sectors(IF_MV2(cur_cmd.lun,) 461 int result = storage_write_sectors(IF_MV2(cur_cmd.lun,)
464 cur_cmd.sector, 462 cur_cmd.sector,
465 MIN(BUFFER_SIZE/SECTOR_SIZE, 463 MIN(BUFFER_SIZE/SECTOR_SIZE,
466 cur_cmd.count), 464 cur_cmd.count),
@@ -639,7 +637,7 @@ static void send_and_read_next(void)
639 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 637 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
640 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 638 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
641#else 639#else
642 cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,) 640 cur_cmd.last_result = storage_read_sectors(IF_MV2(cur_cmd.lun,)
643 cur_cmd.sector, 641 cur_cmd.sector,
644 MIN(BUFFER_SIZE/SECTOR_SIZE, 642 MIN(BUFFER_SIZE/SECTOR_SIZE,
645 cur_cmd.count), 643 cur_cmd.count),
@@ -654,6 +652,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
654 /* USB Mass Storage assumes LBA capability. 652 /* USB Mass Storage assumes LBA capability.
655 TODO: support 48-bit LBA */ 653 TODO: support 48-bit LBA */
656 654
655 struct storage_info info;
657 unsigned int length = cbw->data_transfer_length; 656 unsigned int length = cbw->data_transfer_length;
658 unsigned int block_size = 0; 657 unsigned int block_size = 0;
659 unsigned int block_count = 0; 658 unsigned int block_count = 0;
@@ -664,25 +663,20 @@ static void handle_scsi(struct command_block_wrapper* cbw)
664 unsigned char lun = cbw->lun; 663 unsigned char lun = cbw->lun;
665#endif 664#endif
666 unsigned int block_size_mult = 1; 665 unsigned int block_size_mult = 1;
666 storage_get_info(IF_MV2(lun,)&info);
667#ifdef USB_USE_RAMDISK 667#ifdef USB_USE_RAMDISK
668 block_size = SECTOR_SIZE; 668 block_size = SECTOR_SIZE;
669 block_count = RAMDISK_SIZE; 669 block_count = RAMDISK_SIZE;
670#else 670#else
671#if (CONFIG_STORAGE & STORAGE_SD) || defined(HAVE_HOTSWAP) 671 block_size=info.sector_size;
672 tCardInfo* cinfo = card_get_info(lun); 672 block_count=info.num_sectors;
673 if(cinfo->initialized && cinfo->numblocks > 0) { 673#endif
674 block_size = cinfo->blocksize; 674
675 block_count = cinfo->numblocks; 675#ifdef HAVE_HOTSWAP
676 } 676 if(storage_removable(IF_MV(lun)) && !storage_present(IF_MV(lun))) {
677 else {
678 ejected[lun] = true; 677 ejected[lun] = true;
679 try_release_ata(); 678 try_release_ata();
680 } 679 }
681#else
682 unsigned short* identify = ata_get_identify();
683 block_size = SECTOR_SIZE;
684 block_count = (identify[61] << 16 | identify[60]);
685#endif
686#endif 680#endif
687 681
688 if(ejected[lun]) 682 if(ejected[lun])
@@ -719,19 +713,22 @@ static void handle_scsi(struct command_block_wrapper* cbw)
719 case SCSI_REPORT_LUNS: { 713 case SCSI_REPORT_LUNS: {
720 logf("scsi inquiry %d",lun); 714 logf("scsi inquiry %d",lun);
721 int allocation_length=0; 715 int allocation_length=0;
716 int i;
722 allocation_length|=(cbw->command_block[6]<<24); 717 allocation_length|=(cbw->command_block[6]<<24);
723 allocation_length|=(cbw->command_block[7]<<16); 718 allocation_length|=(cbw->command_block[7]<<16);
724 allocation_length|=(cbw->command_block[8]<<8); 719 allocation_length|=(cbw->command_block[8]<<8);
725 allocation_length|=(cbw->command_block[9]); 720 allocation_length|=(cbw->command_block[9]);
726 memset(tb.lun_data,0,sizeof(struct report_lun_data)); 721 memset(tb.lun_data,0,sizeof(struct report_lun_data));
722 tb.lun_data->lun_list_length=htobe32(8*NUM_VOLUMES);
723 for(i=0;i<NUM_VOLUMES;i++)
724 {
727#ifdef HAVE_HOTSWAP 725#ifdef HAVE_HOTSWAP
728 tb.lun_data->lun_list_length=htobe32(16); 726 if(storage_removable(IF_MV(i)))
729 tb.lun_data->lun1[1]=1; 727 tb.lun_data->luns[i][1]=1;
730#else 728 else
731 tb.lun_data->lun_list_length=htobe32(8);
732#endif 729#endif
733 tb.lun_data->lun0[1]=0; 730 tb.lun_data->luns[i][1]=0;
734 731 }
735 send_command_result(tb.lun_data, 732 send_command_result(tb.lun_data,
736 MIN(sizeof(struct report_lun_data), length)); 733 MIN(sizeof(struct report_lun_data), length));
737 break; 734 break;
@@ -739,7 +736,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
739 736
740 case SCSI_INQUIRY: 737 case SCSI_INQUIRY:
741 logf("scsi inquiry %d",lun); 738 logf("scsi inquiry %d",lun);
742 identify2inquiry(lun); 739 fill_inquiry(IF_MV(lun));
743 length = MIN(length, cbw->command_block[4]); 740 length = MIN(length, cbw->command_block[4]);
744 send_command_result(tb.inquiry, 741 send_command_result(tb.inquiry,
745 MIN(sizeof(struct inquiry_data), length)); 742 MIN(sizeof(struct inquiry_data), length));
@@ -975,7 +972,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
975 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 972 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
976 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 973 MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
977#else 974#else
978 cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,) 975 cur_cmd.last_result = storage_read_sectors(IF_MV2(cur_cmd.lun,)
979 cur_cmd.sector, 976 cur_cmd.sector,
980 MIN(BUFFER_SIZE/SECTOR_SIZE, 977 MIN(BUFFER_SIZE/SECTOR_SIZE,
981 cur_cmd.count), 978 cur_cmd.count),
@@ -1072,46 +1069,30 @@ static void send_csw(int status)
1072 } 1069 }
1073} 1070}
1074 1071
1075/* convert ATA IDENTIFY to SCSI INQUIRY */ 1072static void copy_padded(char *dest, char *src, int len)
1076static void identify2inquiry(int lun)
1077{ 1073{
1078#ifdef HAVE_FLASH_STORAGE 1074 int i=0;
1079 if(lun==0) { 1075 while(src[i]!=0 && i<len)
1080 memcpy(&tb.inquiry->VendorId,"Rockbox ",8); 1076 {
1081 memcpy(&tb.inquiry->ProductId,"Internal Storage",16); 1077 dest[i]=src[i];
1082 memcpy(&tb.inquiry->ProductRevisionLevel,"0.00",4); 1078 i++;
1083 } 1079 }
1084 else { 1080 while(i<len)
1085 memcpy(&tb.inquiry->VendorId,"Rockbox ",8); 1081 {
1086 memcpy(&tb.inquiry->ProductId,"SD Card Slot ",16); 1082 dest[i]=' ';
1087 memcpy(&tb.inquiry->ProductRevisionLevel,"0.00",4); 1083 i++;
1088 } 1084 }
1089#else 1085}
1090 unsigned int i;
1091 unsigned short* dest;
1092 unsigned short* src;
1093 unsigned short* identify = ata_get_identify();
1094 (void)lun;
1095 memset(tb.inquiry, 0, sizeof(struct inquiry_data));
1096
1097#if 0
1098 if (identify[82] & 4)
1099 tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
1100#endif
1101 1086
1102 /* ATA only has a 'model' field, so we copy the 1087/* build SCSI INQUIRY */
1103 first 8 bytes to 'vendor' and the rest to 'product' (they are 1088static void fill_inquiry(IF_MV_NONVOID(int lun))
1104 consecutive in the inquiry struct) */ 1089{
1105 src = (unsigned short*)&identify[27]; 1090 memset(tb.inquiry, 0, sizeof(struct inquiry_data));
1106 dest = (unsigned short*)&tb.inquiry->VendorId; 1091 struct storage_info info;
1107 for (i=0;i<12;i++) 1092 storage_get_info(IF_MV2(lun,)&info);
1108 dest[i] = htobe16(src[i]); 1093 copy_padded(tb.inquiry->VendorId,info.vendor,sizeof(tb.inquiry->VendorId));
1109 1094 copy_padded(tb.inquiry->ProductId,info.product,sizeof(tb.inquiry->ProductId));
1110 src = (unsigned short*)&identify[23]; 1095 copy_padded(tb.inquiry->ProductRevisionLevel,info.revision,sizeof(tb.inquiry->ProductRevisionLevel));
1111 dest = (unsigned short*)&tb.inquiry->ProductRevisionLevel;
1112 for (i=0;i<2;i++)
1113 dest[i] = htobe16(src[i]);
1114#endif
1115 1096
1116 tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE; 1097 tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE;
1117 tb.inquiry->AdditionalLength = 0x1f; 1098 tb.inquiry->AdditionalLength = 0x1f;
@@ -1119,14 +1100,6 @@ static void identify2inquiry(int lun)
1119 tb.inquiry->Versions = 4; /* SPC-2 */ 1100 tb.inquiry->Versions = 4; /* SPC-2 */
1120 tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */ 1101 tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
1121 1102
1122#if 0
1123#ifdef HAVE_HOTSWAP
1124 if(lun>0)
1125 tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
1126#endif
1127#endif
1128 /* Mac OSX 10.5 doesn't like this driver if DEVICE_REMOVABLE is not set.
1129 TODO : this can probably be solved by providing caching mode page */
1130#ifdef TOSHIBA_GIGABEAT_S 1103#ifdef TOSHIBA_GIGABEAT_S
1131 tb.inquiry->DeviceTypeModifier = 0; 1104 tb.inquiry->DeviceTypeModifier = 0;
1132#else 1105#else