diff options
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 316 |
1 files changed, 250 insertions, 66 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index b852475663..1fbfe5296d 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "logf.h" | 24 | #include "logf.h" |
25 | #include "ata.h" | 25 | #include "ata.h" |
26 | #include "hotswap.h" | 26 | #include "hotswap.h" |
27 | #include "disk.h" | ||
27 | 28 | ||
28 | #define SECTOR_SIZE 512 | 29 | #define SECTOR_SIZE 512 |
29 | 30 | ||
@@ -40,14 +41,20 @@ | |||
40 | #define SCSI_TEST_UNIT_READY 0x00 | 41 | #define SCSI_TEST_UNIT_READY 0x00 |
41 | #define SCSI_INQUIRY 0x12 | 42 | #define SCSI_INQUIRY 0x12 |
42 | #define SCSI_MODE_SENSE 0x1a | 43 | #define SCSI_MODE_SENSE 0x1a |
44 | #define SCSI_REQUEST_SENSE 0x03 | ||
43 | #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e | 45 | #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e |
44 | #define SCSI_READ_CAPACITY 0x25 | 46 | #define SCSI_READ_CAPACITY 0x25 |
47 | #define SCSI_READ_FORMAT_CAPACITY 0x23 | ||
45 | #define SCSI_READ_10 0x28 | 48 | #define SCSI_READ_10 0x28 |
46 | #define SCSI_WRITE_10 0x2a | 49 | #define SCSI_WRITE_10 0x2a |
50 | #define SCSI_START_STOP_UNIT 0x1b | ||
47 | 51 | ||
48 | #define SCSI_STATUS_GOOD 0x00 | 52 | #define SCSI_STATUS_GOOD 0x00 |
53 | #define SCSI_STATUS_FAIL 0x01 | ||
49 | #define SCSI_STATUS_CHECK_CONDITION 0x02 | 54 | #define SCSI_STATUS_CHECK_CONDITION 0x02 |
50 | 55 | ||
56 | #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 | ||
57 | |||
51 | 58 | ||
52 | struct inquiry_data { | 59 | struct inquiry_data { |
53 | unsigned char DeviceType; | 60 | unsigned char DeviceType; |
@@ -62,6 +69,20 @@ struct inquiry_data { | |||
62 | unsigned char ProductRevisionLevel[4]; | 69 | unsigned char ProductRevisionLevel[4]; |
63 | } __attribute__ ((packed)); | 70 | } __attribute__ ((packed)); |
64 | 71 | ||
72 | struct sense_data { | ||
73 | unsigned char ResponseCode; | ||
74 | unsigned char Obsolete; | ||
75 | unsigned char filemark_eom_ili_sensekey; | ||
76 | unsigned int Information; | ||
77 | unsigned char AdditionalSenseLength; | ||
78 | unsigned int CommandSpecificInformation; | ||
79 | unsigned char AdditionalSenseCode; | ||
80 | unsigned char AdditionalSenseCodeQualifier; | ||
81 | unsigned char FieldReplaceableUnitCode; | ||
82 | unsigned char SKSV; | ||
83 | unsigned short SenseKeySpecific; | ||
84 | } __attribute__ ((packed)); | ||
85 | |||
65 | struct command_block_wrapper { | 86 | struct command_block_wrapper { |
66 | unsigned int signature; | 87 | unsigned int signature; |
67 | unsigned int tag; | 88 | unsigned int tag; |
@@ -84,26 +105,34 @@ struct capacity { | |||
84 | unsigned int block_size; | 105 | unsigned int block_size; |
85 | } __attribute__ ((packed)); | 106 | } __attribute__ ((packed)); |
86 | 107 | ||
108 | struct format_capacity { | ||
109 | unsigned int following_length; | ||
110 | unsigned int block_count; | ||
111 | unsigned int block_size; | ||
112 | } __attribute__ ((packed)); | ||
113 | |||
87 | /* the ARC USB controller can at most buffer 16KB unaligned data */ | 114 | /* the ARC USB controller can at most buffer 16KB unaligned data */ |
88 | static unsigned char _transfer_buffer[16384]; | 115 | static unsigned char _transfer_buffer[16384*8] __attribute((aligned (4096))); |
89 | static unsigned char* transfer_buffer; | 116 | static unsigned char* transfer_buffer; |
90 | static struct inquiry_data _inquiry; | 117 | static struct inquiry_data _inquiry CACHEALIGN_ATTR; |
91 | static struct inquiry_data* inquiry; | 118 | static struct inquiry_data* inquiry; |
92 | static struct capacity _capacity_data; | 119 | static struct capacity _capacity_data CACHEALIGN_ATTR; |
93 | static struct capacity* capacity_data; | 120 | static struct capacity* capacity_data; |
94 | 121 | static struct format_capacity _format_capacity_data CACHEALIGN_ATTR; | |
95 | //static unsigned char partial_sector[SECTOR_SIZE]; | 122 | static struct format_capacity* format_capacity_data; |
123 | static struct sense_data _sense_data CACHEALIGN_ATTR; | ||
124 | static struct sense_data *sense_data; | ||
96 | 125 | ||
97 | static struct { | 126 | static struct { |
98 | unsigned int sector; | 127 | unsigned int sector; |
99 | unsigned int offset; /* if partial sector */ | ||
100 | unsigned int count; | 128 | unsigned int count; |
101 | unsigned int tag; | 129 | unsigned int tag; |
130 | unsigned int lun; | ||
102 | } current_cmd; | 131 | } current_cmd; |
103 | 132 | ||
104 | void handle_scsi(struct command_block_wrapper* cbw); | 133 | static void handle_scsi(struct command_block_wrapper* cbw); |
105 | void send_csw(unsigned int tag, int status); | 134 | static void send_csw(unsigned int tag, int status); |
106 | static void identify2inquiry(void); | 135 | static void identify2inquiry(int lun); |
107 | 136 | ||
108 | static enum { | 137 | static enum { |
109 | IDLE, | 138 | IDLE, |
@@ -117,7 +146,10 @@ void usb_storage_init(void) | |||
117 | inquiry = (void*)UNCACHED_ADDR(&_inquiry); | 146 | inquiry = (void*)UNCACHED_ADDR(&_inquiry); |
118 | transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); | 147 | transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); |
119 | capacity_data = (void*)UNCACHED_ADDR(&_capacity_data); | 148 | capacity_data = (void*)UNCACHED_ADDR(&_capacity_data); |
120 | identify2inquiry(); | 149 | format_capacity_data = (void*)UNCACHED_ADDR(&_format_capacity_data); |
150 | sense_data = (void*)UNCACHED_ADDR(&_sense_data); | ||
151 | state = IDLE; | ||
152 | logf("usb_storage_init done"); | ||
121 | } | 153 | } |
122 | 154 | ||
123 | /* called by usb_core_transfer_complete() */ | 155 | /* called by usb_core_transfer_complete() */ |
@@ -128,21 +160,44 @@ void usb_storage_transfer_complete(int endpoint) | |||
128 | switch (endpoint) { | 160 | switch (endpoint) { |
129 | case EP_RX: | 161 | case EP_RX: |
130 | //logf("ums: %d bytes in", length); | 162 | //logf("ums: %d bytes in", length); |
131 | switch (state) { | 163 | if(state == RECEIVING) |
132 | case IDLE: | 164 | { |
133 | handle_scsi(cbw); | 165 | int receive_count=usb_drv_get_last_transfer_length(); |
134 | break; | 166 | logf("scsi write %d %d", current_cmd.sector, current_cmd.count); |
135 | 167 | if(usb_drv_get_last_transfer_status()==0) | |
136 | default: | 168 | { |
137 | break; | 169 | if((unsigned int)receive_count!=(SECTOR_SIZE*current_cmd.count)) |
170 | { | ||
171 | logf("%d >= %d",SECTOR_SIZE*current_cmd.count,receive_count); | ||
172 | } | ||
173 | ata_write_sectors(IF_MV2(current_cmd.lun,) | ||
174 | current_cmd.sector, current_cmd.count, | ||
175 | transfer_buffer); | ||
176 | send_csw(current_cmd.tag, SCSI_STATUS_GOOD); | ||
177 | } | ||
178 | else | ||
179 | { | ||
180 | logf("Transfer failed %X",usb_drv_get_last_transfer_status()); | ||
181 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | ||
182 | } | ||
138 | } | 183 | } |
139 | 184 | else | |
140 | /* re-prime endpoint */ | 185 | { |
141 | usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); | 186 | state = SENDING; |
187 | handle_scsi(cbw); | ||
188 | } | ||
189 | |||
142 | break; | 190 | break; |
143 | 191 | ||
144 | case EP_TX: | 192 | case EP_TX: |
145 | //logf("ums: %d bytes out", length); | 193 | //logf("ums: out complete"); |
194 | if(state != IDLE) | ||
195 | { | ||
196 | /* re-prime endpoint. We only need room for commands */ | ||
197 | state = IDLE; | ||
198 | usb_drv_recv(EP_RX, transfer_buffer, 1024); | ||
199 | } | ||
200 | |||
146 | break; | 201 | break; |
147 | } | 202 | } |
148 | } | 203 | } |
@@ -156,7 +211,7 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
156 | 211 | ||
157 | switch (req->bRequest) { | 212 | switch (req->bRequest) { |
158 | case USB_BULK_GET_MAX_LUN: { | 213 | case USB_BULK_GET_MAX_LUN: { |
159 | static char maxlun = 0; | 214 | static char maxlun = NUM_VOLUMES - 1; |
160 | logf("ums: getmaxlun"); | 215 | logf("ums: getmaxlun"); |
161 | usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1); | 216 | usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1); |
162 | usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ | 217 | usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ |
@@ -174,8 +229,9 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
174 | 229 | ||
175 | case USB_REQ_SET_CONFIGURATION: | 230 | case USB_REQ_SET_CONFIGURATION: |
176 | logf("ums: set config"); | 231 | logf("ums: set config"); |
177 | /* prime rx endpoint */ | 232 | /* prime rx endpoint. We only need room for commands */ |
178 | usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer); | 233 | state = IDLE; |
234 | usb_drv_recv(EP_RX, transfer_buffer, 1024); | ||
179 | handled = true; | 235 | handled = true; |
180 | break; | 236 | break; |
181 | } | 237 | } |
@@ -185,50 +241,138 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
185 | 241 | ||
186 | /****************************************************************************/ | 242 | /****************************************************************************/ |
187 | 243 | ||
188 | void handle_scsi(struct command_block_wrapper* cbw) | 244 | static void handle_scsi(struct command_block_wrapper* cbw) |
189 | { | 245 | { |
190 | /* USB Mass Storage assumes LBA capability. | 246 | /* USB Mass Storage assumes LBA capability. |
191 | TODO: support 48-bit LBA */ | 247 | TODO: support 48-bit LBA */ |
192 | 248 | ||
249 | unsigned int sectors_per_transfer=0; | ||
193 | unsigned int length = cbw->data_transfer_length; | 250 | unsigned int length = cbw->data_transfer_length; |
251 | unsigned int block_size; | ||
252 | unsigned char lun = cbw->lun; | ||
253 | unsigned int block_size_mult = 1; | ||
254 | #ifdef HAVE_HOTSWAP | ||
255 | tCardInfo* cinfo = card_get_info(lun); | ||
256 | block_size = cinfo->blocksize; | ||
257 | if(cinfo->initialized==1) | ||
258 | { | ||
259 | sectors_per_transfer=(sizeof _transfer_buffer/ block_size); | ||
260 | } | ||
261 | #else | ||
262 | block_size = SECTOR_SIZE; | ||
263 | sectors_per_transfer=(sizeof _transfer_buffer/ block_size); | ||
264 | #endif | ||
265 | |||
266 | #ifdef MAX_LOG_SECTOR_SIZE | ||
267 | block_size_mult = disk_sector_multiplier; | ||
268 | #endif | ||
194 | 269 | ||
195 | switch (cbw->command_block[0]) { | 270 | switch (cbw->command_block[0]) { |
196 | case SCSI_TEST_UNIT_READY: | 271 | case SCSI_TEST_UNIT_READY: |
197 | logf("scsi test_unit_ready"); | 272 | logf("scsi test_unit_ready %d",lun); |
273 | #ifdef HAVE_HOTSWAP | ||
274 | if(cinfo->initialized==1) | ||
275 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
276 | else | ||
277 | send_csw(cbw->tag, SCSI_STATUS_FAIL); | ||
278 | #else | ||
198 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 279 | send_csw(cbw->tag, SCSI_STATUS_GOOD); |
280 | #endif | ||
199 | break; | 281 | break; |
200 | 282 | ||
201 | case SCSI_INQUIRY: | 283 | case SCSI_INQUIRY: |
202 | logf("scsi inquiry"); | 284 | logf("scsi inquiry %d",lun); |
285 | identify2inquiry(lun); | ||
203 | length = MIN(length, cbw->command_block[4]); | 286 | length = MIN(length, cbw->command_block[4]); |
204 | usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length)); | 287 | usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length)); |
205 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 288 | send_csw(cbw->tag, SCSI_STATUS_GOOD); |
206 | break; | 289 | break; |
207 | 290 | ||
291 | case SCSI_REQUEST_SENSE: { | ||
292 | sense_data->ResponseCode=0x70; | ||
293 | sense_data->filemark_eom_ili_sensekey=2; | ||
294 | sense_data->Information=2; | ||
295 | sense_data->AdditionalSenseLength=10; | ||
296 | sense_data->CommandSpecificInformation=0; | ||
297 | sense_data->AdditionalSenseCode=0x3a; | ||
298 | sense_data->AdditionalSenseCodeQualifier=0; | ||
299 | sense_data->FieldReplaceableUnitCode=0; | ||
300 | sense_data->SKSV=0; | ||
301 | sense_data->SenseKeySpecific=0; | ||
302 | logf("scsi request_sense %d",lun); | ||
303 | usb_drv_send(EP_TX, sense_data, | ||
304 | sizeof(_sense_data)); | ||
305 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
306 | break; | ||
307 | } | ||
308 | |||
208 | case SCSI_MODE_SENSE: { | 309 | case SCSI_MODE_SENSE: { |
209 | static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 310 | static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
210 | logf("scsi mode_sense"); | 311 | logf("scsi mode_sense %d",lun); |
211 | usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data), | 312 | usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data), |
212 | MIN(sizeof sense_data, length)); | 313 | MIN(sizeof sense_data, length)); |
213 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 314 | send_csw(cbw->tag, SCSI_STATUS_GOOD); |
214 | break; | 315 | break; |
215 | } | 316 | } |
216 | 317 | ||
318 | case SCSI_START_STOP_UNIT: | ||
319 | logf("scsi start_stop unit %d",lun); | ||
320 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
321 | break; | ||
322 | |||
217 | case SCSI_ALLOW_MEDIUM_REMOVAL: | 323 | case SCSI_ALLOW_MEDIUM_REMOVAL: |
218 | logf("scsi allow_medium_removal"); | 324 | logf("scsi allow_medium_removal %d",lun); |
325 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
326 | break; | ||
327 | |||
328 | case SCSI_READ_FORMAT_CAPACITY: { | ||
329 | logf("scsi read_format_capacity %d",lun); | ||
330 | format_capacity_data->following_length=htobe32(8); | ||
331 | #ifdef HAVE_HOTSWAP | ||
332 | /* Careful: "block count" actually means "number of last block" */ | ||
333 | if(cinfo->initialized==1) | ||
334 | { | ||
335 | format_capacity_data->block_count = htobe32(cinfo->numblocks - 1); | ||
336 | format_capacity_data->block_size = htobe32(cinfo->blocksize); | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | format_capacity_data->block_count = htobe32(0); | ||
341 | format_capacity_data->block_size = htobe32(0); | ||
342 | } | ||
343 | #else | ||
344 | unsigned short* identify = ata_get_identify(); | ||
345 | /* Careful: "block count" actually means "number of last block" */ | ||
346 | format_capacity_data->block_count = htobe32((identify[61] << 16 | identify[60]) / block_size_mult - 1); | ||
347 | format_capacity_data->block_size = htobe32(block_size * block_size_mult); | ||
348 | #endif | ||
349 | format_capacity_data->block_size |= SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA; | ||
350 | |||
351 | usb_drv_send(EP_TX, format_capacity_data, | ||
352 | MIN(sizeof _format_capacity_data, length)); | ||
219 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 353 | send_csw(cbw->tag, SCSI_STATUS_GOOD); |
220 | break; | 354 | break; |
355 | } | ||
221 | 356 | ||
222 | case SCSI_READ_CAPACITY: { | 357 | case SCSI_READ_CAPACITY: { |
223 | logf("scsi read_capacity"); | 358 | logf("scsi read_capacity %d",lun); |
224 | #ifdef HAVE_FLASH_STORAGE | 359 | #ifdef HAVE_HOTSWAP |
225 | tCardInfo* cinfo = card_get_info(0); | 360 | /* Careful: "block count" actually means "number of last block" */ |
226 | capacity_data->block_count = htobe32(cinfo->numblocks); | 361 | if(cinfo->initialized==1) |
227 | capacity_data->block_size = htobe32(cinfo->blocksize); | 362 | { |
363 | capacity_data->block_count = htobe32(cinfo->numblocks - 1); | ||
364 | capacity_data->block_size = htobe32(cinfo->blocksize); | ||
365 | } | ||
366 | else | ||
367 | { | ||
368 | capacity_data->block_count = htobe32(0); | ||
369 | capacity_data->block_size = htobe32(0); | ||
370 | } | ||
228 | #else | 371 | #else |
229 | unsigned short* identify = ata_get_identify(); | 372 | unsigned short* identify = ata_get_identify(); |
230 | capacity_data->block_count = htobe32(identify[60] << 16 | identify[61]); | 373 | /* Careful : "block count" actually means the number of the last block */ |
231 | capacity_data->block_size = htobe32(SECTOR_SIZE); | 374 | capacity_data->block_count = htobe32((identify[61] << 16 | identify[60]) / block_size_mult - 1); |
375 | capacity_data->block_size = htobe32(block_size * block_size_mult); | ||
232 | #endif | 376 | #endif |
233 | usb_drv_send(EP_TX, capacity_data, | 377 | usb_drv_send(EP_TX, capacity_data, |
234 | MIN(sizeof _capacity_data, length)); | 378 | MIN(sizeof _capacity_data, length)); |
@@ -237,43 +381,71 @@ void handle_scsi(struct command_block_wrapper* cbw) | |||
237 | } | 381 | } |
238 | 382 | ||
239 | case SCSI_READ_10: | 383 | case SCSI_READ_10: |
240 | current_cmd.sector = | 384 | current_cmd.sector = block_size_mult * |
241 | cbw->command_block[2] << 24 | | 385 | (cbw->command_block[2] << 24 | |
242 | cbw->command_block[3] << 16 | | 386 | cbw->command_block[3] << 16 | |
243 | cbw->command_block[4] << 8 | | 387 | cbw->command_block[4] << 8 | |
244 | cbw->command_block[5] ; | 388 | cbw->command_block[5] ); |
245 | current_cmd.count = | 389 | current_cmd.count = block_size_mult * |
246 | cbw->command_block[7] << 16 | | 390 | (cbw->command_block[7] << 16 | |
247 | cbw->command_block[8]; | 391 | cbw->command_block[8]); |
248 | current_cmd.offset = 0; | ||
249 | current_cmd.tag = cbw->tag; | 392 | current_cmd.tag = cbw->tag; |
393 | current_cmd.lun = cbw->lun; | ||
250 | 394 | ||
251 | logf("scsi read %d %d", current_cmd.sector, current_cmd.count); | 395 | //logf("scsi read %d %d", current_cmd.sector, current_cmd.count); |
252 | 396 | ||
253 | /* too much? */ | 397 | //logf("Asked for %d sectors",current_cmd.count); |
254 | if (current_cmd.count > (sizeof _transfer_buffer / SECTOR_SIZE)) { | 398 | if(current_cmd.count > sectors_per_transfer) |
255 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | 399 | { |
256 | break; | 400 | current_cmd.count = sectors_per_transfer; |
257 | } | 401 | } |
402 | //logf("Sending %d sectors",current_cmd.count); | ||
258 | 403 | ||
259 | ata_read_sectors(IF_MV2(0,) current_cmd.sector, current_cmd.count, | 404 | if(current_cmd.count*block_size > sizeof(_transfer_buffer)) { |
260 | transfer_buffer); | 405 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); |
261 | state = SENDING; | 406 | } |
262 | usb_drv_send(EP_TX, transfer_buffer, | 407 | else { |
263 | MIN(current_cmd.count * SECTOR_SIZE, length)); | 408 | ata_read_sectors(IF_MV2(lun,) current_cmd.sector, |
409 | current_cmd.count, transfer_buffer); | ||
410 | usb_drv_send(EP_TX, transfer_buffer, | ||
411 | current_cmd.count*block_size); | ||
412 | send_csw(current_cmd.tag, SCSI_STATUS_GOOD); | ||
413 | } | ||
264 | break; | 414 | break; |
265 | 415 | ||
266 | case SCSI_WRITE_10: | 416 | case SCSI_WRITE_10: |
267 | logf("scsi write10"); | 417 | //logf("scsi write10"); |
418 | current_cmd.sector = block_size_mult * | ||
419 | (cbw->command_block[2] << 24 | | ||
420 | cbw->command_block[3] << 16 | | ||
421 | cbw->command_block[4] << 8 | | ||
422 | cbw->command_block[5] ); | ||
423 | current_cmd.count = block_size_mult * | ||
424 | (cbw->command_block[7] << 16 | | ||
425 | cbw->command_block[8]); | ||
426 | current_cmd.tag = cbw->tag; | ||
427 | current_cmd.lun = cbw->lun; | ||
428 | /* expect data */ | ||
429 | if(current_cmd.count*block_size > sizeof(_transfer_buffer)) { | ||
430 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | ||
431 | } | ||
432 | else { | ||
433 | usb_drv_recv(EP_RX, transfer_buffer, | ||
434 | current_cmd.count*block_size); | ||
435 | state = RECEIVING; | ||
436 | } | ||
437 | |||
268 | break; | 438 | break; |
269 | 439 | ||
270 | default: | 440 | default: |
271 | logf("scsi unknown cmd %x", cbw->command_block[0]); | 441 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); |
442 | usb_drv_stall(EP_TX, true); | ||
443 | send_csw(current_cmd.tag, SCSI_STATUS_GOOD); | ||
272 | break; | 444 | break; |
273 | } | 445 | } |
274 | } | 446 | } |
275 | 447 | ||
276 | void send_csw(unsigned int tag, int status) | 448 | static void send_csw(unsigned int tag, int status) |
277 | { | 449 | { |
278 | static struct command_status_wrapper _csw; | 450 | static struct command_status_wrapper _csw; |
279 | struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw); | 451 | struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw); |
@@ -287,16 +459,23 @@ void send_csw(unsigned int tag, int status) | |||
287 | } | 459 | } |
288 | 460 | ||
289 | /* convert ATA IDENTIFY to SCSI INQUIRY */ | 461 | /* convert ATA IDENTIFY to SCSI INQUIRY */ |
290 | static void identify2inquiry(void) | 462 | static void identify2inquiry(int lun) |
291 | { | 463 | { |
292 | unsigned int i; | ||
293 | #ifdef HAVE_FLASH_STORAGE | 464 | #ifdef HAVE_FLASH_STORAGE |
294 | for (i=0; i<8; i++) | 465 | if(lun==0) |
295 | inquiry->VendorId[i] = i + 'A'; | 466 | { |
296 | 467 | memcpy(&inquiry->VendorId,"Rockbox ",8); | |
297 | for (i=0; i<8; i++) | 468 | memcpy(&inquiry->ProductId,"Internal Storage",16); |
298 | inquiry->ProductId[i] = i + 'm'; | 469 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); |
470 | } | ||
471 | else | ||
472 | { | ||
473 | memcpy(&inquiry->VendorId,"Rockbox ",8); | ||
474 | memcpy(&inquiry->ProductId,"SD Card Slot ",16); | ||
475 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); | ||
476 | } | ||
299 | #else | 477 | #else |
478 | unsigned int i; | ||
300 | unsigned short* dest; | 479 | unsigned short* dest; |
301 | unsigned short* src; | 480 | unsigned short* src; |
302 | unsigned short* identify = ata_get_identify(); | 481 | unsigned short* identify = ata_get_identify(); |
@@ -310,22 +489,27 @@ static void identify2inquiry(void) | |||
310 | src = (unsigned short*)&identify[27]; | 489 | src = (unsigned short*)&identify[27]; |
311 | dest = (unsigned short*)&inquiry->VendorId; | 490 | dest = (unsigned short*)&inquiry->VendorId; |
312 | for (i=0;i<4;i++) | 491 | for (i=0;i<4;i++) |
313 | dest[i] = src[i]; | 492 | dest[i] = htobe16(src[i]); |
314 | 493 | ||
315 | src = (unsigned short*)&identify[27+8]; | 494 | src = (unsigned short*)&identify[27+8]; |
316 | dest = (unsigned short*)&inquiry->ProductId; | 495 | dest = (unsigned short*)&inquiry->ProductId; |
317 | for (i=0;i<8;i++) | 496 | for (i=0;i<8;i++) |
318 | dest[i] = src[i]; | 497 | dest[i] = htobe16(src[i]); |
319 | 498 | ||
320 | src = (unsigned short*)&identify[23]; | 499 | src = (unsigned short*)&identify[23]; |
321 | dest = (unsigned short*)&inquiry->ProductRevisionLevel; | 500 | dest = (unsigned short*)&inquiry->ProductRevisionLevel; |
322 | for (i=0;i<2;i++) | 501 | for (i=0;i<2;i++) |
323 | dest[i] = src[i]; | 502 | dest[i] = htobe16(src[i]); |
324 | #endif | 503 | #endif |
325 | 504 | ||
326 | inquiry->DeviceType = DIRECT_ACCESS_DEVICE; | 505 | inquiry->DeviceType = DIRECT_ACCESS_DEVICE; |
327 | inquiry->AdditionalLength = 0x1f; | 506 | inquiry->AdditionalLength = 0x1f; |
328 | inquiry->Versions = 3; /* ANSI SCSI level 2 */ | 507 | inquiry->Versions = 3; /* ANSI SCSI level 2 */ |
329 | inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */ | 508 | inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */ |
509 | |||
510 | #ifdef HAVE_HOTSWAP | ||
511 | inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | ||
512 | #endif | ||
513 | |||
330 | } | 514 | } |
331 | 515 | ||