1
0
Fork 0
forked from len0rd/rockbox

usb: Multiple improvements:

* Support varying-sized logical sectors in a single build, instead
   of a hardcoded SECTOR_SIZE.
 * Properly truncate READ CAPACITY(10) if drive has over 2^32 sectors
   And fix potential alignment issues
 * Properly truncate READ_FORMAT_CAPACITY if drive has over 2^32 sectors
 * Support READ CAPACITY(16)

Change-Id: I744b8629131f9ede31e1a972a6700b2244f2e798
This commit is contained in:
Solomon Peachy 2024-11-02 10:04:57 -04:00
parent fa4bdf5744
commit 209aeff5b1

View file

@ -106,8 +106,9 @@
#define SCSI_MODE_SENSE_10 0x5a #define SCSI_MODE_SENSE_10 0x5a
#define SCSI_REQUEST_SENSE 0x03 #define SCSI_REQUEST_SENSE 0x03
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
#define SCSI_READ_CAPACITY 0x25 #define SCSI_READ_CAPACITY_10 0x25
#define SCSI_READ_FORMAT_CAPACITY 0x23 #define SCSI_READ_CAPACITY_16 0x9e
#define USB_UFI_READ_FORMAT_CAPACITY 0x23
#define SCSI_READ_10 0x28 #define SCSI_READ_10 0x28
#define SCSI_WRITE_10 0x2a #define SCSI_WRITE_10 0x2a
#define SCSI_START_STOP_UNIT 0x1b #define SCSI_START_STOP_UNIT 0x1b
@ -248,9 +249,16 @@ struct command_status_wrapper {
unsigned char status; unsigned char status;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct capacity { struct capacity_10 {
unsigned int block_count; unsigned char block_count[4];
unsigned int block_size; unsigned char block_size[4];
} __attribute__ ((packed));
struct capacity_16 {
unsigned char block_count[8];
unsigned char block_size[4];
unsigned char flags[2];
unsigned char lowest_aligned_lba[2];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct format_capacity { struct format_capacity {
@ -263,7 +271,8 @@ struct format_capacity {
static union { static union {
unsigned char* transfer_buffer; unsigned char* transfer_buffer;
struct inquiry_data* inquiry; struct inquiry_data* inquiry;
struct capacity* capacity_data; struct capacity_10* capacity_data_10;
struct capacity_16* capacity_data_16;
struct format_capacity* format_capacity_data; struct format_capacity* format_capacity_data;
struct sense_data *sense_data; struct sense_data *sense_data;
struct mode_sense_data_6 *ms_data_6; struct mode_sense_data_6 *ms_data_6;
@ -278,8 +287,8 @@ static char *cbw_buffer;
static struct { static struct {
sector_t sector; sector_t sector;
unsigned int count; unsigned int count;
unsigned int orig_count;
unsigned int cur_cmd; unsigned int cur_cmd;
unsigned int block_size;
unsigned int tag; unsigned int tag;
unsigned int lun; unsigned int lun;
unsigned char *data[2]; unsigned char *data[2];
@ -501,6 +510,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
#endif #endif
logf("transfer result for ep %d/%d %X %d", ep,dir,status, length); logf("transfer result for ep %d/%d %X %d", ep,dir,status, length);
switch(state) { switch(state) {
case RECEIVING_BLOCKS: case RECEIVING_BLOCKS:
if(dir==USB_DIR_IN) { if(dir==USB_DIR_IN) {
@ -508,37 +518,37 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
} }
logf("scsi write %llu %d", cur_cmd.sector, cur_cmd.count); logf("scsi write %llu %d", cur_cmd.sector, cur_cmd.count);
if(status==0) { if(status==0) {
if((unsigned int)length!=(SECTOR_SIZE* cur_cmd.count) if((unsigned int)length!=(cur_cmd.block_size* cur_cmd.count)
&& (unsigned int)length!=WRITE_BUFFER_SIZE) { && (unsigned int)length!=WRITE_BUFFER_SIZE) {
logf("unexpected length :%d",length); logf("unexpected length :%d",length);
break; break;
} }
sector_t next_sector = cur_cmd.sector + sector_t next_sector = cur_cmd.sector +
(WRITE_BUFFER_SIZE/SECTOR_SIZE); (WRITE_BUFFER_SIZE/cur_cmd.block_size);
unsigned int next_count = cur_cmd.count - unsigned int next_count = cur_cmd.count -
MIN(cur_cmd.count,WRITE_BUFFER_SIZE/SECTOR_SIZE); MIN(cur_cmd.count,WRITE_BUFFER_SIZE/cur_cmd.block_size);
int next_select = !cur_cmd.data_select; int next_select = !cur_cmd.data_select;
if(next_count!=0) { if(next_count!=0) {
/* Ask the host to send more, to the other buffer */ /* Ask the host to send more, to the other buffer */
receive_block_data(cur_cmd.data[next_select], receive_block_data(cur_cmd.data[next_select],
MIN(WRITE_BUFFER_SIZE,next_count*SECTOR_SIZE)); MIN(WRITE_BUFFER_SIZE,next_count*cur_cmd.block_size));
} }
/* Now write the data that just came in, while the host is /* Now write the data that just came in, while the host is
sending the next bit */ sending the next bit */
#ifdef USB_USE_RAMDISK #ifdef USB_USE_RAMDISK
memcpy(ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, memcpy(ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
cur_cmd.data[cur_cmd.data_select], cur_cmd.data[cur_cmd.data_select],
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); MIN(WRITE_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count)*cur_cmd.block_size);
#else #else
int result = USBSTOR_WRITE_SECTORS_FILTER(); int result = USBSTOR_WRITE_SECTORS_FILTER();
if (result == 0) { if (result == 0) {
result = storage_write_sectors(IF_MD(cur_cmd.lun,) result = storage_write_sectors(IF_MD(cur_cmd.lun,)
cur_cmd.sector, cur_cmd.sector,
MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), MIN(WRITE_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
cur_cmd.data[cur_cmd.data_select]); cur_cmd.data[cur_cmd.data_select]);
} }
@ -712,25 +722,25 @@ static void send_and_read_next(void)
cur_cmd.last_result = result; cur_cmd.last_result = result;
send_block_data(cur_cmd.data[cur_cmd.data_select], send_block_data(cur_cmd.data[cur_cmd.data_select],
MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); MIN(READ_BUFFER_SIZE,cur_cmd.count*cur_cmd.block_size));
/* Switch buffers for the next one */ /* Switch buffers for the next one */
cur_cmd.data_select=!cur_cmd.data_select; cur_cmd.data_select=!cur_cmd.data_select;
cur_cmd.sector+=(READ_BUFFER_SIZE/SECTOR_SIZE); cur_cmd.sector+=(READ_BUFFER_SIZE/cur_cmd.block_size);
cur_cmd.count-=MIN(cur_cmd.count,READ_BUFFER_SIZE/SECTOR_SIZE); cur_cmd.count-=MIN(cur_cmd.count,READ_BUFFER_SIZE/cur_cmd.block_size);
if(cur_cmd.count!=0) { if(cur_cmd.count!=0) {
/* already read the next bit, so we can send it out immediately when the /* already read the next bit, so we can send it out immediately when the
* current transfer completes. */ * current transfer completes. */
#ifdef USB_USE_RAMDISK #ifdef USB_USE_RAMDISK
memcpy(cur_cmd.data[cur_cmd.data_select], memcpy(cur_cmd.data[cur_cmd.data_select],
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count)*cur_cmd.block_size);
#else #else
result = storage_read_sectors(IF_MD(cur_cmd.lun,) result = storage_read_sectors(IF_MD(cur_cmd.lun,)
cur_cmd.sector, cur_cmd.sector,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
cur_cmd.data[cur_cmd.data_select]); cur_cmd.data[cur_cmd.data_select]);
if(cur_cmd.last_result == 0) if(cur_cmd.last_result == 0)
cur_cmd.last_result = result; cur_cmd.last_result = result;
@ -748,7 +758,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
unsigned int block_size; unsigned int block_size;
bool lun_present=true; bool lun_present=true;
unsigned char lun = cbw->lun; unsigned char lun = cbw->lun;
unsigned int block_size_mult = 1;
if(letoh32(cbw->signature) != CBW_SIGNATURE) { if(letoh32(cbw->signature) != CBW_SIGNATURE) {
logf("ums: bad cbw signature (%x)", cbw->signature); logf("ums: bad cbw signature (%x)", cbw->signature);
@ -783,10 +792,14 @@ static void handle_scsi(struct command_block_wrapper* cbw)
if(ejected[lun]) if(ejected[lun])
lun_present = false; lun_present = false;
unsigned int block_size_mult = 1; /* Number of LOGICAL storage device blocks in each USB block */
#ifdef MAX_LOG_SECTOR_SIZE #ifdef MAX_LOG_SECTOR_SIZE
block_size_mult = disk_get_sector_multiplier(IF_MD(lun)); block_size_mult = disk_get_sector_multiplier(IF_MD(lun));
#endif #endif
uint32_t bsize = block_size*block_size_mult;
sector_t bcount = block_count/block_size_mult;
cur_cmd.tag = cbw->tag; cur_cmd.tag = cbw->tag;
cur_cmd.lun = lun; cur_cmd.lun = lun;
cur_cmd.cur_cmd = cbw->command_block[0]; cur_cmd.cur_cmd = cbw->command_block[0];
@ -887,31 +900,33 @@ static void handle_scsi(struct command_block_wrapper* cbw)
htobe16(sizeof(struct mode_sense_bdesc_longlba)); htobe16(sizeof(struct mode_sense_bdesc_longlba));
memset(tb.ms_data_10->block_descriptor.reserved,0,4); memset(tb.ms_data_10->block_descriptor.reserved,0,4);
memset(tb.ms_data_10->block_descriptor.num_blocks,0,8);
#ifdef STORAGE_64BIT_SECTOR #ifdef STORAGE_64BIT_SECTOR
tb.ms_data_10->block_descriptor.num_blocks[2] = tb.ms_data_10->block_descriptor.num_blocks[2] =
((block_count/block_size_mult) & 0xff00000000ULL)>>40; (bcount & 0xff00000000ULL)>>40;
tb.ms_data_10->block_descriptor.num_blocks[3] = tb.ms_data_10->block_descriptor.num_blocks[3] =
((block_count/block_size_mult) & 0x00ff000000ULL)>>32; (bcount & 0x00ff000000ULL)>>32;
#else
tb.ms_data_10->block_descriptor.num_blocks[2] = 0;
tb.ms_data_10->block_descriptor.num_blocks[3] = 0;
#endif #endif
tb.ms_data_10->block_descriptor.num_blocks[4] = tb.ms_data_10->block_descriptor.num_blocks[4] =
((block_count/block_size_mult) & 0xff000000)>>24; (bcount & 0xff000000)>>24;
tb.ms_data_10->block_descriptor.num_blocks[5] = tb.ms_data_10->block_descriptor.num_blocks[5] =
((block_count/block_size_mult) & 0x00ff0000)>>16; (bcount & 0x00ff0000)>>16;
tb.ms_data_10->block_descriptor.num_blocks[6] = tb.ms_data_10->block_descriptor.num_blocks[6] =
((block_count/block_size_mult) & 0x0000ff00)>>8; (bcount & 0x0000ff00)>>8;
tb.ms_data_10->block_descriptor.num_blocks[7] = tb.ms_data_10->block_descriptor.num_blocks[7] =
((block_count/block_size_mult) & 0x000000ff); (bcount & 0x000000ff);
tb.ms_data_10->block_descriptor.block_size[0] = tb.ms_data_10->block_descriptor.block_size[0] =
((block_size*block_size_mult) & 0xff000000)>>24; (bsize & 0xff000000)>>24;
tb.ms_data_10->block_descriptor.block_size[1] = tb.ms_data_10->block_descriptor.block_size[1] =
((block_size*block_size_mult) & 0x00ff0000)>>16; (bsize & 0x00ff0000)>>16;
tb.ms_data_10->block_descriptor.block_size[2] = tb.ms_data_10->block_descriptor.block_size[2] =
((block_size*block_size_mult) & 0x0000ff00)>>8; (bsize & 0x0000ff00)>>8;
tb.ms_data_10->block_descriptor.block_size[3] = tb.ms_data_10->block_descriptor.block_size[3] =
((block_size*block_size_mult) & 0x000000ff); (bsize & 0x000000ff);
send_command_result(tb.ms_data_10, send_command_result(tb.ms_data_10,
MIN(sizeof(struct mode_sense_data_10), length)); MIN(sizeof(struct mode_sense_data_10), length));
break; break;
@ -947,25 +962,24 @@ static void handle_scsi(struct command_block_wrapper* cbw)
sizeof(struct mode_sense_bdesc_shortlba); sizeof(struct mode_sense_bdesc_shortlba);
tb.ms_data_6->block_descriptor.density_code = 0; tb.ms_data_6->block_descriptor.density_code = 0;
tb.ms_data_6->block_descriptor.reserved = 0; tb.ms_data_6->block_descriptor.reserved = 0;
if(block_count/block_size_mult > 0xffffff) { if(bcount > 0xffffff) {
tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff; tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff;
tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff; tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff;
tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff; tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff;
} } else {
else {
tb.ms_data_6->block_descriptor.num_blocks[0] = tb.ms_data_6->block_descriptor.num_blocks[0] =
((block_count/block_size_mult) & 0xff0000)>>16; (bcount & 0xff0000)>>16;
tb.ms_data_6->block_descriptor.num_blocks[1] = tb.ms_data_6->block_descriptor.num_blocks[1] =
((block_count/block_size_mult) & 0x00ff00)>>8; (bcount & 0x00ff00)>>8;
tb.ms_data_6->block_descriptor.num_blocks[2] = tb.ms_data_6->block_descriptor.num_blocks[2] =
((block_count/block_size_mult) & 0x0000ff); (bcount & 0x0000ff);
} }
tb.ms_data_6->block_descriptor.block_size[0] = tb.ms_data_6->block_descriptor.block_size[0] =
((block_size*block_size_mult) & 0xff0000)>>16; (bsize & 0xff0000)>>16;
tb.ms_data_6->block_descriptor.block_size[1] = tb.ms_data_6->block_descriptor.block_size[1] =
((block_size*block_size_mult) & 0x00ff00)>>8; (bsize & 0x00ff00)>>8;
tb.ms_data_6->block_descriptor.block_size[2] = tb.ms_data_6->block_descriptor.block_size[2] =
((block_size*block_size_mult) & 0x0000ff); (bsize & 0x0000ff);
send_command_result(tb.ms_data_6, send_command_result(tb.ms_data_6,
MIN(sizeof(struct mode_sense_data_6), length)); MIN(sizeof(struct mode_sense_data_6), length));
break; break;
@ -1009,15 +1023,16 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_GOOD); send_csw(UMS_STATUS_GOOD);
break; break;
case SCSI_READ_FORMAT_CAPACITY: { case USB_UFI_READ_FORMAT_CAPACITY: {
logf("scsi read_format_capacity %d",lun); logf("usb ufi read_format_capacity %d",lun);
if(lun_present) { if(lun_present) {
tb.format_capacity_data->following_length=htobe32(8); tb.format_capacity_data->following_length=htobe32(8);
/* "block count" actually means "number of last block" */ /* "block count" actually means "number of last block" */
tb.format_capacity_data->block_count = if (bcount > 0xffffffff)
htobe32(block_count/block_size_mult - 1); tb.format_capacity_data->block_count = 0xffffffff;
tb.format_capacity_data->block_size = else
htobe32(block_size*block_size_mult); tb.format_capacity_data->block_count = htobe32(bcount - 1);
tb.format_capacity_data->block_size = htobe32(bsize);
tb.format_capacity_data->block_size |= tb.format_capacity_data->block_size |=
htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA); htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA);
@ -1033,20 +1048,30 @@ static void handle_scsi(struct command_block_wrapper* cbw)
break; break;
} }
case SCSI_READ_CAPACITY: { case SCSI_READ_CAPACITY_10: {
logf("scsi read_capacity %d",lun); logf("scsi read_capacity10 %d",lun);
if(lun_present) { if(lun_present) {
/* "block count" actually means "number of last block" */ /* "block count" actually means "number of last block" */
tb.capacity_data->block_count = if (bcount >= 0xffffffff) {
htobe32(block_count/block_size_mult - 1); tb.capacity_data_10->block_count[0] = 0xff;
tb.capacity_data->block_size = tb.capacity_data_10->block_count[1] = 0xff;
htobe32(block_size*block_size_mult); tb.capacity_data_10->block_count[2] = 0xff;
tb.capacity_data_10->block_count[3] = 0xff;
send_command_result(tb.capacity_data, } else {
MIN(sizeof(struct capacity), length)); tb.capacity_data_10->block_count[0] = ((bcount-1) & 0xff000000)>>24;
tb.capacity_data_10->block_count[1] = ((bcount-1) & 0x00ff0000)>>16;
tb.capacity_data_10->block_count[2] = ((bcount-1) & 0x0000ff00)>>8;
tb.capacity_data_10->block_count[3] = ((bcount-1) & 0x000000ff);
} }
else { tb.capacity_data_10->block_size[0] = (bsize & 0xff000000)>>24;
tb.capacity_data_10->block_size[1] = (bsize & 0x00ff0000)>>16;
tb.capacity_data_10->block_size[2] = (bsize & 0x0000ff00)>>8;
tb.capacity_data_10->block_size[3] = (bsize & 0x000000ff);
send_command_result(tb.capacity_data_10,
MIN(sizeof(struct capacity_10), length));
} else {
send_command_failed_result(); send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY; cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
@ -1054,7 +1079,59 @@ static void handle_scsi(struct command_block_wrapper* cbw)
} }
break; break;
} }
case SCSI_READ_CAPACITY_16: {
logf("scsi read_capacity16 %d",lun);
if(lun_present) {
/* "block count" actually means "number of last block" */
#ifdef STORAGE_64BIT_SECTOR
tb.capacity_data_16->block_count[2] =
((bcount-1) & 0xff00000000ULL)>>40;
tb.capacity_data_16->block_count[3] =
((bcount-1) & 0x00ff000000ULL)>>32;
#else
tb.capacity_data_16->block_count[2] = 0;
tb.capacity_data_16->block_count[3] = 0;
#endif
tb.capacity_data_16->block_count[4] =
((bcount-1) & 0xff000000)>>24;
tb.capacity_data_16->block_count[5] =
((bcount-1) & 0x00ff0000)>>16;
tb.capacity_data_16->block_count[6] =
((bcount-1) & 0x0000ff00)>>8;
tb.capacity_data_16->block_count[7] =
((bcount-1) & 0x000000ff);
tb.ms_data_10->block_descriptor.block_size[0] =
(bsize & 0xff000000)>>24;
tb.ms_data_10->block_descriptor.block_size[1] =
(bsize & 0x00ff0000)>>16;
tb.ms_data_10->block_descriptor.block_size[2] =
(bsize & 0x0000ff00)>>8;
tb.ms_data_10->block_descriptor.block_size[3] =
(bsize & 0x000000ff);
tb.capacity_data_16->block_size[0] = (bsize & 0xff000000)>>24;
tb.capacity_data_16->block_size[1] = (bsize & 0x00ff0000)>>16;
tb.capacity_data_16->block_size[2] = (bsize & 0x0000ff00)>>8;
tb.capacity_data_16->block_size[3] = (bsize & 0x000000ff);
uint16_t flags = htobe16((1<<12) | find_first_set_bit(block_size_mult));
memcpy(tb.capacity_data_16->flags, &flags, sizeof(flags));
tb.capacity_data_16->lowest_aligned_lba[0] = 0;
tb.capacity_data_16->lowest_aligned_lba[1] = 1;
send_command_result(tb.capacity_data_16,
MIN(sizeof(struct capacity_16), length));
} else {
send_command_failed_result();
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
cur_sense_data.ascq=0;
}
break;
}
case SCSI_READ_10: case SCSI_READ_10:
logf("scsi read10 %d",lun); logf("scsi read10 %d",lun);
if(!lun_present) { if(!lun_present) {
@ -1075,7 +1152,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
cur_cmd.count = block_size_mult * cur_cmd.count = block_size_mult *
(cbw->command_block[7] << 8 | (cbw->command_block[7] << 8 |
cbw->command_block[8]); cbw->command_block[8]);
cur_cmd.orig_count = cur_cmd.count; cur_cmd.block_size = block_size;
logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count); logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
@ -1088,12 +1165,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
else { else {
#ifdef USB_USE_RAMDISK #ifdef USB_USE_RAMDISK
memcpy(cur_cmd.data[cur_cmd.data_select], memcpy(cur_cmd.data[cur_cmd.data_select],
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE); MIN(READ_BUFFER_SIZE/cur_cmd.block_size,cur_cmd.count)*cur_cmd.block_size);
#else #else
cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,) cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,)
cur_cmd.sector, cur_cmd.sector,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
cur_cmd.data[cur_cmd.data_select]); cur_cmd.data[cur_cmd.data_select]);
#endif #endif
send_and_read_next(); send_and_read_next();
@ -1126,7 +1203,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
cbw->command_block[11] << 16 | cbw->command_block[11] << 16 |
cbw->command_block[12] << 8 | cbw->command_block[12] << 8 |
cbw->command_block[13]); cbw->command_block[13]);
cur_cmd.orig_count = cur_cmd.count; cur_cmd.block_size = block_size;
logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count); logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
@ -1139,12 +1216,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
else { else {
#ifdef USB_USE_RAMDISK #ifdef USB_USE_RAMDISK
memcpy(cur_cmd.data[cur_cmd.data_select], memcpy(cur_cmd.data[cur_cmd.data_select],
ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE); MIN(READ_BUFFER_SIZE/cur_cmd.block_size,cur_cmd.count)*cur_cmd.block_size);
#else #else
cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,) cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,)
cur_cmd.sector, cur_cmd.sector,
MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
cur_cmd.data[cur_cmd.data_select]); cur_cmd.data[cur_cmd.data_select]);
#endif #endif
send_and_read_next(); send_and_read_next();
@ -1171,7 +1248,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
cur_cmd.count = block_size_mult * cur_cmd.count = block_size_mult *
(cbw->command_block[7] << 8 | (cbw->command_block[7] << 8 |
cbw->command_block[8]); cbw->command_block[8]);
cur_cmd.orig_count = cur_cmd.count; cur_cmd.block_size = block_size;
/* expect data */ /* expect data */
if((cur_cmd.sector + cur_cmd.count) > block_count) { if((cur_cmd.sector + cur_cmd.count) > block_count) {
@ -1182,7 +1259,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
} }
else { else {
receive_block_data(cur_cmd.data[0], receive_block_data(cur_cmd.data[0],
MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); MIN(WRITE_BUFFER_SIZE, cur_cmd.count*cur_cmd.block_size));
} }
break; break;
#ifdef STORAGE_64BIT_SECTOR #ifdef STORAGE_64BIT_SECTOR
@ -1212,7 +1289,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
cbw->command_block[11] << 16 | cbw->command_block[11] << 16 |
cbw->command_block[12] << 8 | cbw->command_block[12] << 8 |
cbw->command_block[13]); cbw->command_block[13]);
cur_cmd.orig_count = cur_cmd.count; cur_cmd.block_size = block_size;
/* expect data */ /* expect data */
if((cur_cmd.sector + cur_cmd.count) > block_count) { if((cur_cmd.sector + cur_cmd.count) > block_count) {
@ -1223,7 +1300,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
} }
else { else {
receive_block_data(cur_cmd.data[0], receive_block_data(cur_cmd.data[0],
MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); MIN(WRITE_BUFFER_SIZE, cur_cmd.count*cur_cmd.block_size));
} }
break; break;
#endif #endif