summaryrefslogtreecommitdiff
path: root/firmware/usbstack/usb_storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r--firmware/usbstack/usb_storage.c116
1 files changed, 108 insertions, 8 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 81d90d01db..e226c15f99 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -114,6 +114,9 @@
114#define SCSI_REPORT_LUNS 0xa0 114#define SCSI_REPORT_LUNS 0xa0
115#define SCSI_WRITE_BUFFER 0x3b 115#define SCSI_WRITE_BUFFER 0x3b
116 116
117#define SCSI_READ_16 0x88
118#define SCSI_WRITE_16 0x8a
119
117#define UMS_STATUS_GOOD 0x00 120#define UMS_STATUS_GOOD 0x00
118#define UMS_STATUS_FAIL 0x01 121#define UMS_STATUS_FAIL 0x01
119 122
@@ -273,7 +276,7 @@ static union {
273static char *cbw_buffer; 276static char *cbw_buffer;
274 277
275static struct { 278static struct {
276 unsigned int sector; 279 sector_t sector;
277 unsigned int count; 280 unsigned int count;
278 unsigned int orig_count; 281 unsigned int orig_count;
279 unsigned int cur_cmd; 282 unsigned int cur_cmd;
@@ -503,7 +506,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
503 if(dir==USB_DIR_IN) { 506 if(dir==USB_DIR_IN) {
504 logf("IN received in RECEIVING"); 507 logf("IN received in RECEIVING");
505 } 508 }
506 logf("scsi write %d %d", cur_cmd.sector, cur_cmd.count); 509 logf("scsi write %llu %d", cur_cmd.sector, cur_cmd.count);
507 if(status==0) { 510 if(status==0) {
508 if((unsigned int)length!=(SECTOR_SIZE* cur_cmd.count) 511 if((unsigned int)length!=(SECTOR_SIZE* cur_cmd.count)
509 && (unsigned int)length!=WRITE_BUFFER_SIZE) { 512 && (unsigned int)length!=WRITE_BUFFER_SIZE) {
@@ -511,7 +514,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
511 break; 514 break;
512 } 515 }
513 516
514 unsigned int next_sector = cur_cmd.sector + 517 sector_t next_sector = cur_cmd.sector +
515 (WRITE_BUFFER_SIZE/SECTOR_SIZE); 518 (WRITE_BUFFER_SIZE/SECTOR_SIZE);
516 unsigned int next_count = cur_cmd.count - 519 unsigned int next_count = cur_cmd.count -
517 MIN(cur_cmd.count,WRITE_BUFFER_SIZE/SECTOR_SIZE); 520 MIN(cur_cmd.count,WRITE_BUFFER_SIZE/SECTOR_SIZE);
@@ -739,12 +742,10 @@ static void send_and_read_next(void)
739 742
740static void handle_scsi(struct command_block_wrapper* cbw) 743static void handle_scsi(struct command_block_wrapper* cbw)
741{ 744{
742 /* USB Mass Storage assumes LBA capability.
743 TODO: support 48-bit LBA */
744
745 struct storage_info info; 745 struct storage_info info;
746 unsigned int length = cbw->data_transfer_length; 746 unsigned int length = cbw->data_transfer_length;
747 unsigned int block_size, block_count; 747 sector_t block_count;
748 unsigned int block_size;
748 bool lun_present=true; 749 bool lun_present=true;
749 unsigned char lun = cbw->lun; 750 unsigned char lun = cbw->lun;
750 unsigned int block_size_mult = 1; 751 unsigned int block_size_mult = 1;
@@ -888,6 +889,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
888 memset(tb.ms_data_10->block_descriptor.reserved,0,4); 889 memset(tb.ms_data_10->block_descriptor.reserved,0,4);
889 memset(tb.ms_data_10->block_descriptor.num_blocks,0,8); 890 memset(tb.ms_data_10->block_descriptor.num_blocks,0,8);
890 891
892#ifdef STORAGE_64BIT_SECTOR
893 tb.ms_data_10->block_descriptor.num_blocks[2] =
894 ((block_count/block_size_mult) & 0xff00000000ULL)>>40;
895 tb.ms_data_10->block_descriptor.num_blocks[3] =
896 ((block_count/block_size_mult) & 0x00ff000000ULL)>>32;
897#endif
891 tb.ms_data_10->block_descriptor.num_blocks[4] = 898 tb.ms_data_10->block_descriptor.num_blocks[4] =
892 ((block_count/block_size_mult) & 0xff000000)>>24; 899 ((block_count/block_size_mult) & 0xff000000)>>24;
893 tb.ms_data_10->block_descriptor.num_blocks[5] = 900 tb.ms_data_10->block_descriptor.num_blocks[5] =
@@ -1070,7 +1077,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1070 cbw->command_block[8]); 1077 cbw->command_block[8]);
1071 cur_cmd.orig_count = cur_cmd.count; 1078 cur_cmd.orig_count = cur_cmd.count;
1072 1079
1073 //logf("scsi read %d %d", cur_cmd.sector, cur_cmd.count); 1080 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
1074 1081
1075 if((cur_cmd.sector + cur_cmd.count) > block_count) { 1082 if((cur_cmd.sector + cur_cmd.count) > block_count) {
1076 send_csw(UMS_STATUS_FAIL); 1083 send_csw(UMS_STATUS_FAIL);
@@ -1092,7 +1099,58 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1092 send_and_read_next(); 1099 send_and_read_next();
1093 } 1100 }
1094 break; 1101 break;
1102#ifdef STORAGE_64BIT_SECTOR
1103 case SCSI_READ_16:
1104 logf("scsi read16 %d",lun);
1105 if(!lun_present) {
1106 send_command_failed_result();
1107 cur_sense_data.sense_key=SENSE_NOT_READY;
1108 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
1109 cur_sense_data.ascq=0;
1110 break;
1111 }
1112 cur_cmd.data[0] = tb.transfer_buffer;
1113 cur_cmd.data[1] = &tb.transfer_buffer[READ_BUFFER_SIZE];
1114 cur_cmd.data_select=0;
1115 cur_cmd.sector = block_size_mult *
1116 ((uint64_t)cbw->command_block[2] << 56 |
1117 (uint64_t)cbw->command_block[3] << 48 |
1118 (uint64_t)cbw->command_block[4] << 40 |
1119 (uint64_t)cbw->command_block[5] << 32 |
1120 cbw->command_block[6] << 24 |
1121 cbw->command_block[7] << 16 |
1122 cbw->command_block[8] << 8 |
1123 cbw->command_block[9]);
1124 cur_cmd.count = block_size_mult *
1125 (cbw->command_block[10] << 24 |
1126 cbw->command_block[11] << 16 |
1127 cbw->command_block[12] << 8 |
1128 cbw->command_block[13]);
1129 cur_cmd.orig_count = cur_cmd.count;
1095 1130
1131 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
1132
1133 if((cur_cmd.sector + cur_cmd.count) > block_count) {
1134 send_csw(UMS_STATUS_FAIL);
1135 cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
1136 cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE;
1137 cur_sense_data.ascq=0;
1138 }
1139 else {
1140#ifdef USB_USE_RAMDISK
1141 memcpy(cur_cmd.data[cur_cmd.data_select],
1142 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE,
1143 MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE);
1144#else
1145 cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,)
1146 cur_cmd.sector,
1147 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count),
1148 cur_cmd.data[cur_cmd.data_select]);
1149#endif
1150 send_and_read_next();
1151 }
1152 break;
1153#endif
1096 case SCSI_WRITE_10: 1154 case SCSI_WRITE_10:
1097 logf("scsi write10 %d",lun); 1155 logf("scsi write10 %d",lun);
1098 if(!lun_present) { 1156 if(!lun_present) {
@@ -1127,6 +1185,48 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1127 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); 1185 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE));
1128 } 1186 }
1129 break; 1187 break;
1188#ifdef STORAGE_64BIT_SECTOR
1189 case SCSI_WRITE_16:
1190 logf("scsi write16 %d",lun);
1191 if(!lun_present) {
1192 send_csw(UMS_STATUS_FAIL);
1193 cur_sense_data.sense_key=SENSE_NOT_READY;
1194 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
1195 cur_sense_data.ascq=0;
1196 break;
1197 }
1198 cur_cmd.data[0] = tb.transfer_buffer;
1199 cur_cmd.data[1] = &tb.transfer_buffer[WRITE_BUFFER_SIZE];
1200 cur_cmd.data_select=0;
1201 cur_cmd.sector = block_size_mult *
1202 ((uint64_t)cbw->command_block[2] << 56 |
1203 (uint64_t)cbw->command_block[3] << 48 |
1204 (uint64_t)cbw->command_block[4] << 40 |
1205 (uint64_t)cbw->command_block[5] << 32 |
1206 cbw->command_block[6] << 24 |
1207 cbw->command_block[7] << 16 |
1208 cbw->command_block[8] << 8 |
1209 cbw->command_block[9]);
1210 cur_cmd.count = block_size_mult *
1211 (cbw->command_block[10] << 24 |
1212 cbw->command_block[11] << 16 |
1213 cbw->command_block[12] << 8 |
1214 cbw->command_block[13]);
1215 cur_cmd.orig_count = cur_cmd.count;
1216
1217 /* expect data */
1218 if((cur_cmd.sector + cur_cmd.count) > block_count) {
1219 send_csw(UMS_STATUS_FAIL);
1220 cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
1221 cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE;
1222 cur_sense_data.ascq=0;
1223 }
1224 else {
1225 receive_block_data(cur_cmd.data[0],
1226 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE));
1227 }
1228 break;
1229#endif
1130 1230
1131#if CONFIG_RTC 1231#if CONFIG_RTC
1132 case SCSI_WRITE_BUFFER: 1232 case SCSI_WRITE_BUFFER: