1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Frank Gevaerts 2008-11-01 16:14:28 +00:00
parent 646cac0bde
commit 2f8a0081c6
64 changed files with 541 additions and 554 deletions

View file

@ -24,7 +24,7 @@
#include "usb_drv.h"
//#define LOGF_ENABLE
#include "logf.h"
#include "ata.h"
#include "storage.h"
#include "hotswap.h"
#include "disk.h"
/* Needed to get at the audio buffer */
@ -36,7 +36,7 @@
/* The SD card driver on Sansa c200 and e200 can cause write corruption,
* often triggered by simultaneous USB activity. This can be largely avoided
* by not overlapping ata_write_sector() with USB transfers. This does reduce
* by not overlapping storage_write_sector() with USB transfers. This does reduce
* write performance, so we only do it for the affected DAPs
*/
#if (CONFIG_STORAGE & STORAGE_SD)
@ -147,10 +147,8 @@ struct inquiry_data {
struct report_lun_data {
unsigned int lun_list_length;
unsigned int reserved1;
unsigned char lun0[8];
#ifdef HAVE_HOTSWAP
unsigned char lun1[8];
#endif
// TODO this should be cleaned up with the VOLUMES vs DRIVES mess
unsigned char luns[NUM_VOLUMES][8];
} __attribute__ ((packed));
struct sense_data {
@ -263,7 +261,7 @@ static void send_command_result(void *data,int size);
static void send_command_failed_result(void);
static void send_block_data(void *data,int size);
static void receive_block_data(void *data,int size);
static void identify2inquiry(int lun);
static void fill_inquiry(IF_MV_NONVOID(int lun));
static void send_and_read_next(void);
static bool ejected[NUM_VOLUMES];
@ -289,7 +287,7 @@ static bool check_disk_present(IF_MV_NONVOID(int volume))
return true;
#else
unsigned char sector[512];
return ata_read_sectors(IF_MV2(volume,)0,1,sector) == 0;
return storage_read_sectors(IF_MV2(volume,)0,1,sector) == 0;
#endif
}
@ -460,7 +458,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
cur_cmd.data[cur_cmd.data_select],
MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
#else
int result = ata_write_sectors(IF_MV2(cur_cmd.lun,)
int result = storage_write_sectors(IF_MV2(cur_cmd.lun,)
cur_cmd.sector,
MIN(BUFFER_SIZE/SECTOR_SIZE,
cur_cmd.count),
@ -639,7 +637,7 @@ static void send_and_read_next(void)
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
#else
cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,)
cur_cmd.last_result = storage_read_sectors(IF_MV2(cur_cmd.lun,)
cur_cmd.sector,
MIN(BUFFER_SIZE/SECTOR_SIZE,
cur_cmd.count),
@ -654,6 +652,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
/* USB Mass Storage assumes LBA capability.
TODO: support 48-bit LBA */
struct storage_info info;
unsigned int length = cbw->data_transfer_length;
unsigned int block_size = 0;
unsigned int block_count = 0;
@ -664,25 +663,20 @@ static void handle_scsi(struct command_block_wrapper* cbw)
unsigned char lun = cbw->lun;
#endif
unsigned int block_size_mult = 1;
storage_get_info(IF_MV2(lun,)&info);
#ifdef USB_USE_RAMDISK
block_size = SECTOR_SIZE;
block_count = RAMDISK_SIZE;
#else
#if (CONFIG_STORAGE & STORAGE_SD) || defined(HAVE_HOTSWAP)
tCardInfo* cinfo = card_get_info(lun);
if(cinfo->initialized && cinfo->numblocks > 0) {
block_size = cinfo->blocksize;
block_count = cinfo->numblocks;
}
else {
block_size=info.sector_size;
block_count=info.num_sectors;
#endif
#ifdef HAVE_HOTSWAP
if(storage_removable(IF_MV(lun)) && !storage_present(IF_MV(lun))) {
ejected[lun] = true;
try_release_ata();
}
#else
unsigned short* identify = ata_get_identify();
block_size = SECTOR_SIZE;
block_count = (identify[61] << 16 | identify[60]);
#endif
#endif
if(ejected[lun])
@ -719,19 +713,22 @@ static void handle_scsi(struct command_block_wrapper* cbw)
case SCSI_REPORT_LUNS: {
logf("scsi inquiry %d",lun);
int allocation_length=0;
int i;
allocation_length|=(cbw->command_block[6]<<24);
allocation_length|=(cbw->command_block[7]<<16);
allocation_length|=(cbw->command_block[8]<<8);
allocation_length|=(cbw->command_block[9]);
memset(tb.lun_data,0,sizeof(struct report_lun_data));
tb.lun_data->lun_list_length=htobe32(8*NUM_VOLUMES);
for(i=0;i<NUM_VOLUMES;i++)
{
#ifdef HAVE_HOTSWAP
tb.lun_data->lun_list_length=htobe32(16);
tb.lun_data->lun1[1]=1;
#else
tb.lun_data->lun_list_length=htobe32(8);
if(storage_removable(IF_MV(i)))
tb.lun_data->luns[i][1]=1;
else
#endif
tb.lun_data->lun0[1]=0;
tb.lun_data->luns[i][1]=0;
}
send_command_result(tb.lun_data,
MIN(sizeof(struct report_lun_data), length));
break;
@ -739,7 +736,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
case SCSI_INQUIRY:
logf("scsi inquiry %d",lun);
identify2inquiry(lun);
fill_inquiry(IF_MV(lun));
length = MIN(length, cbw->command_block[4]);
send_command_result(tb.inquiry,
MIN(sizeof(struct inquiry_data), length));
@ -975,7 +972,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
MIN(BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE);
#else
cur_cmd.last_result = ata_read_sectors(IF_MV2(cur_cmd.lun,)
cur_cmd.last_result = storage_read_sectors(IF_MV2(cur_cmd.lun,)
cur_cmd.sector,
MIN(BUFFER_SIZE/SECTOR_SIZE,
cur_cmd.count),
@ -1072,46 +1069,30 @@ static void send_csw(int status)
}
}
/* convert ATA IDENTIFY to SCSI INQUIRY */
static void identify2inquiry(int lun)
static void copy_padded(char *dest, char *src, int len)
{
#ifdef HAVE_FLASH_STORAGE
if(lun==0) {
memcpy(&tb.inquiry->VendorId,"Rockbox ",8);
memcpy(&tb.inquiry->ProductId,"Internal Storage",16);
memcpy(&tb.inquiry->ProductRevisionLevel,"0.00",4);
}
else {
memcpy(&tb.inquiry->VendorId,"Rockbox ",8);
memcpy(&tb.inquiry->ProductId,"SD Card Slot ",16);
memcpy(&tb.inquiry->ProductRevisionLevel,"0.00",4);
}
#else
unsigned int i;
unsigned short* dest;
unsigned short* src;
unsigned short* identify = ata_get_identify();
(void)lun;
memset(tb.inquiry, 0, sizeof(struct inquiry_data));
#if 0
if (identify[82] & 4)
tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
#endif
int i=0;
while(src[i]!=0 && i<len)
{
dest[i]=src[i];
i++;
}
while(i<len)
{
dest[i]=' ';
i++;
}
}
/* ATA only has a 'model' field, so we copy the
first 8 bytes to 'vendor' and the rest to 'product' (they are
consecutive in the inquiry struct) */
src = (unsigned short*)&identify[27];
dest = (unsigned short*)&tb.inquiry->VendorId;
for (i=0;i<12;i++)
dest[i] = htobe16(src[i]);
src = (unsigned short*)&identify[23];
dest = (unsigned short*)&tb.inquiry->ProductRevisionLevel;
for (i=0;i<2;i++)
dest[i] = htobe16(src[i]);
#endif
/* build SCSI INQUIRY */
static void fill_inquiry(IF_MV_NONVOID(int lun))
{
memset(tb.inquiry, 0, sizeof(struct inquiry_data));
struct storage_info info;
storage_get_info(IF_MV2(lun,)&info);
copy_padded(tb.inquiry->VendorId,info.vendor,sizeof(tb.inquiry->VendorId));
copy_padded(tb.inquiry->ProductId,info.product,sizeof(tb.inquiry->ProductId));
copy_padded(tb.inquiry->ProductRevisionLevel,info.revision,sizeof(tb.inquiry->ProductRevisionLevel));
tb.inquiry->DeviceType = DIRECT_ACCESS_DEVICE;
tb.inquiry->AdditionalLength = 0x1f;
@ -1119,14 +1100,6 @@ static void identify2inquiry(int lun)
tb.inquiry->Versions = 4; /* SPC-2 */
tb.inquiry->Format = 2; /* SPC-2/3 inquiry format */
#if 0
#ifdef HAVE_HOTSWAP
if(lun>0)
tb.inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
#endif
#endif
/* Mac OSX 10.5 doesn't like this driver if DEVICE_REMOVABLE is not set.
TODO : this can probably be solved by providing caching mode page */
#ifdef TOSHIBA_GIGABEAT_S
tb.inquiry->DeviceTypeModifier = 0;
#else