diff options
Diffstat (limited to 'firmware/usbstack/usb_storage.c')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 604 |
1 files changed, 436 insertions, 168 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index a1faf3d1c4..0904e17e75 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -26,8 +26,22 @@ | |||
26 | #include "hotswap.h" | 26 | #include "hotswap.h" |
27 | #include "disk.h" | 27 | #include "disk.h" |
28 | 28 | ||
29 | #ifdef USB_STORAGE | ||
30 | |||
31 | /* Enable the following define to export only the SD card slot. This | ||
32 | * is useful for USBCV MSC tests, as those are destructive. | ||
33 | * This won't work right if the device doesn't have a card slot. | ||
34 | */ | ||
35 | //#define ONLY_EXPOSE_CARD_SLOT | ||
36 | |||
29 | #define SECTOR_SIZE 512 | 37 | #define SECTOR_SIZE 512 |
30 | 38 | ||
39 | /* We can currently use up to 20k buffer size. More than that requires | ||
40 | * transfer chaining in the driver. Tests on sansa c200 show that the 16k | ||
41 | * limitation causes no more than 2% slowdown. | ||
42 | */ | ||
43 | #define BUFFER_SIZE 16384 | ||
44 | |||
31 | /* bulk-only class specific requests */ | 45 | /* bulk-only class specific requests */ |
32 | #define USB_BULK_RESET_REQUEST 0xff | 46 | #define USB_BULK_RESET_REQUEST 0xff |
33 | #define USB_BULK_GET_MAX_LUN 0xfe | 47 | #define USB_BULK_GET_MAX_LUN 0xfe |
@@ -40,7 +54,8 @@ | |||
40 | 54 | ||
41 | #define SCSI_TEST_UNIT_READY 0x00 | 55 | #define SCSI_TEST_UNIT_READY 0x00 |
42 | #define SCSI_INQUIRY 0x12 | 56 | #define SCSI_INQUIRY 0x12 |
43 | #define SCSI_MODE_SENSE 0x1a | 57 | #define SCSI_MODE_SENSE_6 0x1a |
58 | #define SCSI_MODE_SENSE_10 0x5a | ||
44 | #define SCSI_REQUEST_SENSE 0x03 | 59 | #define SCSI_REQUEST_SENSE 0x03 |
45 | #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e | 60 | #define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e |
46 | #define SCSI_READ_CAPACITY 0x25 | 61 | #define SCSI_READ_CAPACITY 0x25 |
@@ -48,11 +63,23 @@ | |||
48 | #define SCSI_READ_10 0x28 | 63 | #define SCSI_READ_10 0x28 |
49 | #define SCSI_WRITE_10 0x2a | 64 | #define SCSI_WRITE_10 0x2a |
50 | #define SCSI_START_STOP_UNIT 0x1b | 65 | #define SCSI_START_STOP_UNIT 0x1b |
66 | #define SCSI_REPORT_LUNS 0xa0 | ||
51 | 67 | ||
52 | #define SCSI_STATUS_GOOD 0x00 | 68 | #define SCSI_STATUS_GOOD 0x00 |
53 | #define SCSI_STATUS_FAIL 0x01 | 69 | #define SCSI_STATUS_FAIL 0x01 |
54 | #define SCSI_STATUS_CHECK_CONDITION 0x02 | 70 | #define SCSI_STATUS_CHECK_CONDITION 0x02 |
55 | 71 | ||
72 | #define SENSE_NOT_READY 0x02 | ||
73 | #define SENSE_MEDIUM_ERROR 0x03 | ||
74 | #define SENSE_ILLEGAL_REQUEST 0x05 | ||
75 | #define SENSE_UNIT_ATTENTION 0x06 | ||
76 | |||
77 | #define ASC_MEDIUM_NOT_PRESENT 0x3a | ||
78 | #define ASC_INVALID_FIELD_IN_CBD 0x24 | ||
79 | #define ASC_LBA_OUT_OF_RANGE 0x21 | ||
80 | #define ASC_WRITE_ERROR 0x0C | ||
81 | #define ASC_READ_ERROR 0x11 | ||
82 | |||
56 | #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 | 83 | #define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000 |
57 | 84 | ||
58 | 85 | ||
@@ -69,6 +96,15 @@ struct inquiry_data { | |||
69 | unsigned char ProductRevisionLevel[4]; | 96 | unsigned char ProductRevisionLevel[4]; |
70 | } __attribute__ ((packed)); | 97 | } __attribute__ ((packed)); |
71 | 98 | ||
99 | struct report_lun_data { | ||
100 | unsigned int lun_list_length; | ||
101 | unsigned int reserved1; | ||
102 | unsigned char lun0[8]; | ||
103 | #ifdef HAVE_HOTSWAP | ||
104 | unsigned char lun1[8]; | ||
105 | #endif | ||
106 | } __attribute__ ((packed)); | ||
107 | |||
72 | struct sense_data { | 108 | struct sense_data { |
73 | unsigned char ResponseCode; | 109 | unsigned char ResponseCode; |
74 | unsigned char Obsolete; | 110 | unsigned char Obsolete; |
@@ -83,6 +119,21 @@ struct sense_data { | |||
83 | unsigned short SenseKeySpecific; | 119 | unsigned short SenseKeySpecific; |
84 | } __attribute__ ((packed)); | 120 | } __attribute__ ((packed)); |
85 | 121 | ||
122 | struct mode_sense_header_10 { | ||
123 | unsigned short mode_data_length; | ||
124 | unsigned char medium_type; | ||
125 | unsigned char device_specific; | ||
126 | unsigned char reserved1[2]; | ||
127 | unsigned short block_descriptor_length; | ||
128 | } __attribute__ ((packed)); | ||
129 | |||
130 | struct mode_sense_header_6 { | ||
131 | unsigned char mode_data_length; | ||
132 | unsigned char medium_type; | ||
133 | unsigned char device_specific; | ||
134 | unsigned char block_descriptor_length; | ||
135 | } __attribute__ ((packed)); | ||
136 | |||
86 | struct command_block_wrapper { | 137 | struct command_block_wrapper { |
87 | unsigned int signature; | 138 | unsigned int signature; |
88 | unsigned int tag; | 139 | unsigned int tag; |
@@ -111,93 +162,195 @@ struct format_capacity { | |||
111 | unsigned int block_size; | 162 | unsigned int block_size; |
112 | } __attribute__ ((packed)); | 163 | } __attribute__ ((packed)); |
113 | 164 | ||
114 | /* the ARC USB controller can at most buffer 16KB unaligned data */ | 165 | static unsigned char _transfer_buffer[2*BUFFER_SIZE] __attribute((aligned (4096))); |
115 | static unsigned char _transfer_buffer[16384*8] __attribute((aligned (4096))); | ||
116 | static unsigned char* transfer_buffer; | 166 | static unsigned char* transfer_buffer; |
117 | static struct inquiry_data _inquiry CACHEALIGN_ATTR; | 167 | |
118 | static struct inquiry_data* inquiry; | 168 | static struct inquiry_data* inquiry; |
119 | static struct capacity _capacity_data CACHEALIGN_ATTR; | 169 | static unsigned char __inquiry[CACHEALIGN_UP(sizeof(struct inquiry_data))] CACHEALIGN_ATTR; |
170 | |||
120 | static struct capacity* capacity_data; | 171 | static struct capacity* capacity_data; |
121 | static struct format_capacity _format_capacity_data CACHEALIGN_ATTR; | 172 | static unsigned char __capacity_data[CACHEALIGN_UP(sizeof(struct capacity))] CACHEALIGN_ATTR; |
173 | |||
122 | static struct format_capacity* format_capacity_data; | 174 | static struct format_capacity* format_capacity_data; |
123 | static struct sense_data _sense_data CACHEALIGN_ATTR; | 175 | static unsigned char __format_capacity_data[CACHEALIGN_UP(sizeof(struct format_capacity))] CACHEALIGN_ATTR; |
176 | |||
124 | static struct sense_data *sense_data; | 177 | static struct sense_data *sense_data; |
178 | static unsigned char __sense_data[CACHEALIGN_UP(sizeof(struct sense_data))] CACHEALIGN_ATTR; | ||
179 | |||
180 | static struct mode_sense_header_6 *mode_sense_data_6; | ||
181 | static unsigned char __mode_sense_data_6[CACHEALIGN_UP(sizeof(struct mode_sense_header_6))] CACHEALIGN_ATTR; | ||
182 | |||
183 | static struct mode_sense_header_10 *mode_sense_data_10; | ||
184 | static unsigned char __mode_sense_data_10[CACHEALIGN_UP(sizeof(struct mode_sense_header_10))] CACHEALIGN_ATTR; | ||
185 | |||
186 | static struct report_lun_data *lun_data; | ||
187 | static unsigned char __lun_data[CACHEALIGN_UP(sizeof(struct report_lun_data))] CACHEALIGN_ATTR; | ||
188 | |||
189 | static struct command_status_wrapper* csw; | ||
190 | static unsigned char __csw[CACHEALIGN_UP(sizeof(struct command_status_wrapper))] CACHEALIGN_ATTR; | ||
191 | |||
192 | static char *max_lun; | ||
193 | static unsigned char __max_lun[CACHEALIGN_UP(1)] CACHEALIGN_ATTR; | ||
125 | 194 | ||
126 | static struct { | 195 | static struct { |
127 | unsigned int sector; | 196 | unsigned int sector; |
128 | unsigned int count; | 197 | unsigned int count; |
129 | unsigned int tag; | 198 | unsigned int tag; |
130 | unsigned int lun; | 199 | unsigned int lun; |
200 | unsigned char *data[2]; | ||
201 | unsigned char data_select; | ||
202 | unsigned int last_result; | ||
131 | } current_cmd; | 203 | } current_cmd; |
132 | 204 | ||
205 | static struct { | ||
206 | unsigned char sense_key; | ||
207 | unsigned char information; | ||
208 | unsigned char asc; | ||
209 | } cur_sense_data; | ||
210 | |||
133 | static void handle_scsi(struct command_block_wrapper* cbw); | 211 | static void handle_scsi(struct command_block_wrapper* cbw); |
134 | static void send_csw(unsigned int tag, int status); | 212 | static void send_csw(int status); |
213 | static void send_command_result(void *data,int size); | ||
214 | static void send_block_data(void *data,int size); | ||
215 | static void receive_block_data(void *data,int size); | ||
135 | static void identify2inquiry(int lun); | 216 | static void identify2inquiry(int lun); |
217 | static void send_and_read_next(void); | ||
136 | 218 | ||
137 | static enum { | 219 | static enum { |
138 | IDLE, | 220 | WAITING_FOR_COMMAND, |
139 | SENDING, | 221 | SENDING_BLOCKS, |
140 | RECEIVING | 222 | SENDING_RESULT, |
141 | } state = IDLE; | 223 | RECEIVING_BLOCKS, |
224 | SENDING_CSW | ||
225 | } state = WAITING_FOR_COMMAND; | ||
142 | 226 | ||
143 | /* called by usb_code_init() */ | 227 | /* called by usb_code_init() */ |
144 | void usb_storage_init(void) | 228 | void usb_storage_init(void) |
145 | { | 229 | { |
146 | inquiry = (void*)UNCACHED_ADDR(&_inquiry); | ||
147 | transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); | 230 | transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); |
148 | capacity_data = (void*)UNCACHED_ADDR(&_capacity_data); | 231 | inquiry = (void*)UNCACHED_ADDR(&__inquiry); |
149 | format_capacity_data = (void*)UNCACHED_ADDR(&_format_capacity_data); | 232 | capacity_data = (void*)UNCACHED_ADDR(&__capacity_data); |
150 | sense_data = (void*)UNCACHED_ADDR(&_sense_data); | 233 | format_capacity_data = (void*)UNCACHED_ADDR(&__format_capacity_data); |
151 | state = IDLE; | 234 | sense_data = (void*)UNCACHED_ADDR(&__sense_data); |
235 | mode_sense_data_6 = (void*)UNCACHED_ADDR(&__mode_sense_data_6); | ||
236 | mode_sense_data_10 = (void*)UNCACHED_ADDR(&__mode_sense_data_10); | ||
237 | lun_data = (void*)UNCACHED_ADDR(&__lun_data); | ||
238 | max_lun = (void*)UNCACHED_ADDR(&__max_lun); | ||
239 | csw = (void*)UNCACHED_ADDR(&__csw); | ||
152 | logf("usb_storage_init done"); | 240 | logf("usb_storage_init done"); |
153 | } | 241 | } |
154 | 242 | ||
155 | /* called by usb_core_transfer_complete() */ | 243 | /* called by usb_core_transfer_complete() */ |
156 | void usb_storage_transfer_complete(int endpoint) | 244 | void usb_storage_transfer_complete(bool in,int status,int length) |
157 | { | 245 | { |
158 | struct command_block_wrapper* cbw = (void*)transfer_buffer; | 246 | struct command_block_wrapper* cbw = (void*)transfer_buffer; |
159 | 247 | ||
160 | switch (endpoint) { | 248 | //logf("transfer result %X %d", status, length); |
161 | case EP_RX: | 249 | switch(state) { |
162 | //logf("ums: %d bytes in", length); | 250 | case RECEIVING_BLOCKS: |
163 | if(state == RECEIVING) | 251 | if(in==true) { |
164 | { | 252 | logf("IN received in RECEIVING"); |
165 | int receive_count=usb_drv_get_last_transfer_length(); | 253 | } |
166 | logf("scsi write %d %d", current_cmd.sector, current_cmd.count); | 254 | logf("scsi write %d %d", current_cmd.sector, current_cmd.count); |
167 | if(usb_drv_get_last_transfer_status()==0) | 255 | if(status==0) { |
168 | { | 256 | if((unsigned int)length!=(SECTOR_SIZE*current_cmd.count) |
169 | if((unsigned int)receive_count!=(SECTOR_SIZE*current_cmd.count)) | 257 | && (unsigned int)length!=BUFFER_SIZE) { |
170 | { | 258 | logf("unexpected length :%d",length); |
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 | } | 259 | } |
178 | else | 260 | |
179 | { | 261 | unsigned int next_sector = current_cmd.sector + (BUFFER_SIZE/SECTOR_SIZE); |
180 | logf("Transfer failed %X",usb_drv_get_last_transfer_status()); | 262 | unsigned int next_count = current_cmd.count - MIN(current_cmd.count,BUFFER_SIZE/SECTOR_SIZE); |
181 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | 263 | |
264 | if(next_count!=0) { | ||
265 | /* Ask the host to send more, to the other buffer */ | ||
266 | receive_block_data(current_cmd.data[!current_cmd.data_select], | ||
267 | MIN(BUFFER_SIZE,next_count*SECTOR_SIZE)); | ||
182 | } | 268 | } |
269 | |||
270 | /* Now write the data that just came in, while the host is sending the next bit */ | ||
271 | int result = ata_write_sectors(IF_MV2(current_cmd.lun,) | ||
272 | current_cmd.sector, MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), | ||
273 | current_cmd.data[current_cmd.data_select]); | ||
274 | if(result != 0) { | ||
275 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
276 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; | ||
277 | cur_sense_data.asc=ASC_WRITE_ERROR; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | if(next_count==0) { | ||
282 | send_csw(SCSI_STATUS_GOOD); | ||
283 | } | ||
284 | |||
285 | /* Switch buffers for the next one */ | ||
286 | current_cmd.data_select=!current_cmd.data_select; | ||
287 | |||
288 | current_cmd.sector = next_sector; | ||
289 | current_cmd.count = next_count; | ||
290 | |||
183 | } | 291 | } |
184 | else | 292 | else { |
185 | { | 293 | logf("Transfer failed %X",status); |
186 | state = SENDING; | 294 | send_csw(SCSI_STATUS_CHECK_CONDITION); |
187 | handle_scsi(cbw); | 295 | /* TODO fill in cur_sense_data */ |
296 | cur_sense_data.sense_key=0; | ||
297 | cur_sense_data.information=0; | ||
298 | cur_sense_data.asc=0; | ||
188 | } | 299 | } |
189 | |||
190 | break; | 300 | break; |
191 | 301 | case WAITING_FOR_COMMAND: | |
192 | case EP_TX: | 302 | if(in==true) { |
193 | //logf("ums: out complete"); | 303 | logf("IN received in WAITING_FOR_COMMAND"); |
194 | if(state != IDLE) | 304 | } |
195 | { | 305 | //logf("command received"); |
196 | /* re-prime endpoint. We only need room for commands */ | 306 | handle_scsi(cbw); |
197 | state = IDLE; | 307 | break; |
198 | usb_drv_recv(EP_RX, transfer_buffer, 1024); | 308 | case SENDING_CSW: |
309 | if(in==false) { | ||
310 | logf("OUT received in SENDING_CSW"); | ||
311 | } | ||
312 | //logf("csw sent, now go back to idle"); | ||
313 | state = WAITING_FOR_COMMAND; | ||
314 | usb_drv_recv(EP_MASS_STORAGE, transfer_buffer, 1024); | ||
315 | break; | ||
316 | case SENDING_RESULT: | ||
317 | if(in==false) { | ||
318 | logf("OUT received in SENDING"); | ||
319 | } | ||
320 | if(status==0) { | ||
321 | //logf("data sent, now send csw"); | ||
322 | send_csw(SCSI_STATUS_GOOD); | ||
323 | } | ||
324 | else { | ||
325 | logf("Transfer failed %X",status); | ||
326 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
327 | /* TODO fill in cur_sense_data */ | ||
328 | cur_sense_data.sense_key=0; | ||
329 | cur_sense_data.information=0; | ||
330 | cur_sense_data.asc=0; | ||
331 | } | ||
332 | break; | ||
333 | case SENDING_BLOCKS: | ||
334 | if(in==false) { | ||
335 | logf("OUT received in SENDING"); | ||
336 | } | ||
337 | if(status==0) { | ||
338 | if(current_cmd.count==0) { | ||
339 | //logf("data sent, now send csw"); | ||
340 | send_csw(SCSI_STATUS_GOOD); | ||
341 | } | ||
342 | else { | ||
343 | send_and_read_next(); | ||
344 | } | ||
345 | } | ||
346 | else { | ||
347 | logf("Transfer failed %X",status); | ||
348 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
349 | /* TODO fill in cur_sense_data */ | ||
350 | cur_sense_data.sense_key=0; | ||
351 | cur_sense_data.information=0; | ||
352 | cur_sense_data.asc=0; | ||
199 | } | 353 | } |
200 | |||
201 | break; | 354 | break; |
202 | } | 355 | } |
203 | } | 356 | } |
@@ -205,15 +358,24 @@ void usb_storage_transfer_complete(int endpoint) | |||
205 | /* called by usb_core_control_request() */ | 358 | /* called by usb_core_control_request() */ |
206 | bool usb_storage_control_request(struct usb_ctrlrequest* req) | 359 | bool usb_storage_control_request(struct usb_ctrlrequest* req) |
207 | { | 360 | { |
208 | /* note: interrupt context */ | ||
209 | |||
210 | bool handled = false; | 361 | bool handled = false; |
211 | 362 | ||
212 | switch (req->bRequest) { | 363 | switch (req->bRequest) { |
213 | case USB_BULK_GET_MAX_LUN: { | 364 | case USB_BULK_GET_MAX_LUN: { |
214 | static char maxlun = NUM_VOLUMES - 1; | 365 | #ifdef ONLY_EXPOSE_CARD_SLOT |
366 | *max_lun = 0; | ||
367 | #else | ||
368 | *max_lun = NUM_VOLUMES - 1; | ||
369 | #endif | ||
370 | #ifdef HAVE_HOTSWAP | ||
371 | /* Workaround until we find out how to do removable devices properly */ | ||
372 | tCardInfo* cinfo = card_get_info(1); | ||
373 | if(cinfo->initialized==0) { | ||
374 | *max_lun=0; | ||
375 | } | ||
376 | #endif | ||
215 | logf("ums: getmaxlun"); | 377 | logf("ums: getmaxlun"); |
216 | usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1); | 378 | usb_drv_send(EP_CONTROL, UNCACHED_ADDR(max_lun), 1); |
217 | usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ | 379 | usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ |
218 | handled = true; | 380 | handled = true; |
219 | break; | 381 | break; |
@@ -221,8 +383,8 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
221 | 383 | ||
222 | case USB_BULK_RESET_REQUEST: | 384 | case USB_BULK_RESET_REQUEST: |
223 | logf("ums: bulk reset"); | 385 | logf("ums: bulk reset"); |
224 | usb_drv_reset_endpoint(EP_RX, false); | 386 | usb_drv_reset_endpoint(EP_MASS_STORAGE, false); |
225 | usb_drv_reset_endpoint(EP_TX, true); | 387 | usb_drv_reset_endpoint(EP_MASS_STORAGE, true); |
226 | usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ | 388 | usb_drv_send(EP_CONTROL, NULL, 0); /* ack */ |
227 | handled = true; | 389 | handled = true; |
228 | break; | 390 | break; |
@@ -230,8 +392,8 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
230 | case USB_REQ_SET_CONFIGURATION: | 392 | case USB_REQ_SET_CONFIGURATION: |
231 | logf("ums: set config"); | 393 | logf("ums: set config"); |
232 | /* prime rx endpoint. We only need room for commands */ | 394 | /* prime rx endpoint. We only need room for commands */ |
233 | state = IDLE; | 395 | state = WAITING_FOR_COMMAND; |
234 | usb_drv_recv(EP_RX, transfer_buffer, 1024); | 396 | usb_drv_recv(EP_MASS_STORAGE, transfer_buffer, 1024); |
235 | handled = true; | 397 | handled = true; |
236 | break; | 398 | break; |
237 | } | 399 | } |
@@ -239,6 +401,32 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req) | |||
239 | return handled; | 401 | return handled; |
240 | } | 402 | } |
241 | 403 | ||
404 | static void send_and_read_next(void) | ||
405 | { | ||
406 | if(current_cmd.last_result!=0) { | ||
407 | /* The last read failed. */ | ||
408 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
409 | cur_sense_data.sense_key=SENSE_MEDIUM_ERROR; | ||
410 | cur_sense_data.asc=ASC_READ_ERROR; | ||
411 | return; | ||
412 | } | ||
413 | send_block_data(current_cmd.data[current_cmd.data_select], | ||
414 | MIN(BUFFER_SIZE,current_cmd.count*SECTOR_SIZE)); | ||
415 | |||
416 | /* Switch buffers for the next one */ | ||
417 | current_cmd.data_select=!current_cmd.data_select; | ||
418 | |||
419 | current_cmd.sector+=(BUFFER_SIZE/SECTOR_SIZE); | ||
420 | current_cmd.count-=MIN(current_cmd.count,BUFFER_SIZE/SECTOR_SIZE); | ||
421 | |||
422 | if(current_cmd.count!=0){ | ||
423 | /* already read the next bit, so we can send it out immediately when the | ||
424 | * current transfer completes. */ | ||
425 | current_cmd.last_result = ata_read_sectors(IF_MV2(current_cmd.lun,) current_cmd.sector, | ||
426 | MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), | ||
427 | current_cmd.data[current_cmd.data_select]); | ||
428 | } | ||
429 | } | ||
242 | /****************************************************************************/ | 430 | /****************************************************************************/ |
243 | 431 | ||
244 | static void handle_scsi(struct command_block_wrapper* cbw) | 432 | static void handle_scsi(struct command_block_wrapper* cbw) |
@@ -246,141 +434,196 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
246 | /* USB Mass Storage assumes LBA capability. | 434 | /* USB Mass Storage assumes LBA capability. |
247 | TODO: support 48-bit LBA */ | 435 | TODO: support 48-bit LBA */ |
248 | 436 | ||
249 | unsigned int sectors_per_transfer=0; | ||
250 | unsigned int length = cbw->data_transfer_length; | 437 | unsigned int length = cbw->data_transfer_length; |
251 | unsigned int block_size; | 438 | unsigned int block_size; |
439 | unsigned int block_count; | ||
440 | bool lun_present=true; | ||
441 | #ifdef ONLY_EXPOSE_CARD_SLOT | ||
442 | unsigned char lun = cbw->lun+1; | ||
443 | #else | ||
252 | unsigned char lun = cbw->lun; | 444 | unsigned char lun = cbw->lun; |
445 | #endif | ||
253 | unsigned int block_size_mult = 1; | 446 | unsigned int block_size_mult = 1; |
254 | #ifdef HAVE_HOTSWAP | 447 | #ifdef HAVE_HOTSWAP |
255 | tCardInfo* cinfo = card_get_info(lun); | 448 | tCardInfo* cinfo = card_get_info(lun); |
256 | block_size = cinfo->blocksize; | 449 | if(cinfo->initialized==1) { |
257 | if(cinfo->initialized==1) | 450 | block_size = cinfo->blocksize; |
258 | { | 451 | block_count = cinfo->numblocks; |
259 | sectors_per_transfer=(sizeof _transfer_buffer/ block_size); | 452 | } |
453 | else { | ||
454 | lun_present=false; | ||
455 | block_size = 0; | ||
456 | block_count = 0; | ||
260 | } | 457 | } |
261 | #else | 458 | #else |
459 | unsigned short* identify = ata_get_identify(); | ||
262 | block_size = SECTOR_SIZE; | 460 | block_size = SECTOR_SIZE; |
263 | sectors_per_transfer=(sizeof _transfer_buffer/ block_size); | 461 | block_count = (identify[61] << 16 | identify[60]); |
264 | #endif | 462 | #endif |
265 | 463 | ||
266 | #ifdef MAX_LOG_SECTOR_SIZE | 464 | #ifdef MAX_LOG_SECTOR_SIZE |
267 | block_size_mult = disk_sector_multiplier; | 465 | block_size_mult = disk_sector_multiplier; |
268 | #endif | 466 | #endif |
269 | 467 | ||
468 | current_cmd.tag = cbw->tag; | ||
469 | current_cmd.lun = lun; | ||
470 | |||
270 | switch (cbw->command_block[0]) { | 471 | switch (cbw->command_block[0]) { |
271 | case SCSI_TEST_UNIT_READY: | 472 | case SCSI_TEST_UNIT_READY: |
272 | logf("scsi test_unit_ready %d",lun); | 473 | logf("scsi test_unit_ready %d",lun); |
273 | #ifdef HAVE_HOTSWAP | 474 | #ifdef HAVE_HOTSWAP |
274 | if(cinfo->initialized==1) | 475 | if(cinfo->initialized==1) |
275 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 476 | send_csw(SCSI_STATUS_GOOD); |
276 | else | 477 | else { |
277 | send_csw(cbw->tag, SCSI_STATUS_FAIL); | 478 | send_csw(SCSI_STATUS_FAIL); |
479 | cur_sense_data.sense_key=SENSE_NOT_READY; | ||
480 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | ||
481 | } | ||
278 | #else | 482 | #else |
279 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 483 | send_csw(SCSI_STATUS_GOOD); |
280 | #endif | 484 | #endif |
281 | break; | 485 | break; |
282 | 486 | ||
487 | case SCSI_REPORT_LUNS: { | ||
488 | logf("scsi inquiry %d",lun); | ||
489 | int allocation_length=0; | ||
490 | allocation_length|=(cbw->command_block[6]<<24); | ||
491 | allocation_length|=(cbw->command_block[7]<<16); | ||
492 | allocation_length|=(cbw->command_block[8]<<8); | ||
493 | allocation_length|=(cbw->command_block[9]); | ||
494 | memset(lun_data,0,sizeof(struct report_lun_data)); | ||
495 | #ifdef HAVE_HOTSWAP | ||
496 | lun_data->lun_list_length=htobe32(16); | ||
497 | lun_data->lun1[1]=1; | ||
498 | #else | ||
499 | lun_data->lun_list_length=htobe32(8); | ||
500 | #endif | ||
501 | lun_data->lun0[1]=0; | ||
502 | |||
503 | send_command_result(lun_data, MIN(sizeof(struct report_lun_data), length)); | ||
504 | break; | ||
505 | } | ||
506 | |||
283 | case SCSI_INQUIRY: | 507 | case SCSI_INQUIRY: |
284 | logf("scsi inquiry %d",lun); | 508 | logf("scsi inquiry %d",lun); |
285 | identify2inquiry(lun); | 509 | identify2inquiry(lun); |
286 | length = MIN(length, cbw->command_block[4]); | 510 | length = MIN(length, cbw->command_block[4]); |
287 | usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length)); | 511 | send_command_result(inquiry, MIN(sizeof(struct inquiry_data), length)); |
288 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
289 | break; | 512 | break; |
290 | 513 | ||
291 | case SCSI_REQUEST_SENSE: { | 514 | case SCSI_REQUEST_SENSE: { |
292 | sense_data->ResponseCode=0x70; | 515 | sense_data->ResponseCode=0x70;/*current error*/ |
293 | sense_data->filemark_eom_ili_sensekey=2; | 516 | sense_data->filemark_eom_ili_sensekey=cur_sense_data.sense_key&0x0f; |
294 | sense_data->Information=2; | 517 | sense_data->Information=cur_sense_data.information; |
295 | sense_data->AdditionalSenseLength=10; | 518 | sense_data->AdditionalSenseLength=10; |
296 | sense_data->CommandSpecificInformation=0; | 519 | sense_data->CommandSpecificInformation=0; |
297 | sense_data->AdditionalSenseCode=0x3a; | 520 | sense_data->AdditionalSenseCode=cur_sense_data.asc; |
298 | sense_data->AdditionalSenseCodeQualifier=0; | 521 | sense_data->AdditionalSenseCodeQualifier=0; |
299 | sense_data->FieldReplaceableUnitCode=0; | 522 | sense_data->FieldReplaceableUnitCode=0; |
300 | sense_data->SKSV=0; | 523 | sense_data->SKSV=0; |
301 | sense_data->SenseKeySpecific=0; | 524 | sense_data->SenseKeySpecific=0; |
302 | logf("scsi request_sense %d",lun); | 525 | logf("scsi request_sense %d",lun); |
303 | usb_drv_send(EP_TX, sense_data, | 526 | send_command_result(sense_data, sizeof(struct sense_data)); |
304 | sizeof(_sense_data)); | ||
305 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
306 | break; | 527 | break; |
307 | } | 528 | } |
308 | 529 | ||
309 | case SCSI_MODE_SENSE: { | 530 | case SCSI_MODE_SENSE_10: { |
310 | static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 531 | /*unsigned char pc = (cbw->command_block[2] & 0xc0) >>6;*/ |
311 | logf("scsi mode_sense %d",lun); | 532 | unsigned char page_code = cbw->command_block[2] & 0x3f; |
312 | usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data), | 533 | logf("scsi mode_sense_10 %d %X",lun,page_code); |
313 | MIN(sizeof sense_data, length)); | 534 | switch(page_code) { |
314 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 535 | case 0x3f: |
536 | default: | ||
537 | mode_sense_data_10->mode_data_length=0; | ||
538 | mode_sense_data_10->medium_type=0; | ||
539 | mode_sense_data_10->device_specific=0; | ||
540 | mode_sense_data_10->block_descriptor_length=0; | ||
541 | send_command_result(mode_sense_data_10, | ||
542 | MIN(sizeof(struct mode_sense_header_10), length)); | ||
543 | break; | ||
544 | #if 0 | ||
545 | default: | ||
546 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
547 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | ||
548 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; | ||
549 | break; | ||
550 | #endif | ||
551 | } | ||
552 | break; | ||
553 | } | ||
554 | case SCSI_MODE_SENSE_6: { | ||
555 | /*unsigned char pc = (cbw->command_block[2] & 0xc0) >>6;*/ | ||
556 | unsigned char page_code = cbw->command_block[2] & 0x3f; | ||
557 | logf("scsi mode_sense_6 %d %X",lun,page_code); | ||
558 | switch(page_code) { | ||
559 | case 0x3f: | ||
560 | default: | ||
561 | /* All supported pages Since we support only one this is easy*/ | ||
562 | mode_sense_data_6->mode_data_length=0; | ||
563 | mode_sense_data_6->medium_type=0; | ||
564 | mode_sense_data_6->device_specific=0; | ||
565 | mode_sense_data_6->block_descriptor_length=0; | ||
566 | send_command_result(mode_sense_data_6, | ||
567 | MIN(sizeof(struct mode_sense_header_6), length)); | ||
568 | break; | ||
569 | #if 0 | ||
570 | default: | ||
571 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
572 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | ||
573 | cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD; | ||
574 | break; | ||
575 | #endif | ||
576 | } | ||
315 | break; | 577 | break; |
316 | } | 578 | } |
317 | 579 | ||
318 | case SCSI_START_STOP_UNIT: | 580 | case SCSI_START_STOP_UNIT: |
319 | logf("scsi start_stop unit %d",lun); | 581 | logf("scsi start_stop unit %d",lun); |
320 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 582 | send_csw(SCSI_STATUS_GOOD); |
321 | break; | 583 | break; |
322 | 584 | ||
323 | case SCSI_ALLOW_MEDIUM_REMOVAL: | 585 | case SCSI_ALLOW_MEDIUM_REMOVAL: |
324 | logf("scsi allow_medium_removal %d",lun); | 586 | logf("scsi allow_medium_removal %d",lun); |
325 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 587 | /* TODO: use this to show the connect screen ? */ |
588 | send_csw(SCSI_STATUS_GOOD); | ||
326 | break; | 589 | break; |
327 | 590 | ||
328 | case SCSI_READ_FORMAT_CAPACITY: { | 591 | case SCSI_READ_FORMAT_CAPACITY: { |
329 | logf("scsi read_format_capacity %d",lun); | 592 | logf("scsi read_format_capacity %d",lun); |
330 | format_capacity_data->following_length=htobe32(8); | 593 | format_capacity_data->following_length=htobe32(8); |
331 | #ifdef HAVE_HOTSWAP | ||
332 | /* Careful: "block count" actually means "number of last block" */ | 594 | /* Careful: "block count" actually means "number of last block" */ |
333 | if(cinfo->initialized==1) | 595 | format_capacity_data->block_count = htobe32(block_count/block_size_mult - 1); |
334 | { | 596 | format_capacity_data->block_size = htobe32(block_size*block_size_mult); |
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; | 597 | format_capacity_data->block_size |= SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA; |
350 | 598 | ||
351 | usb_drv_send(EP_TX, format_capacity_data, | 599 | send_command_result(format_capacity_data, |
352 | MIN(sizeof _format_capacity_data, length)); | 600 | MIN(sizeof(struct format_capacity), length)); |
353 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | 601 | |
354 | break; | 602 | break; |
355 | } | 603 | } |
356 | 604 | ||
357 | case SCSI_READ_CAPACITY: { | 605 | case SCSI_READ_CAPACITY: { |
358 | logf("scsi read_capacity %d",lun); | 606 | logf("scsi read_capacity %d",lun); |
359 | #ifdef HAVE_HOTSWAP | ||
360 | /* Careful: "block count" actually means "number of last block" */ | 607 | /* Careful: "block count" actually means "number of last block" */ |
361 | if(cinfo->initialized==1) | 608 | capacity_data->block_count = htobe32(block_count/block_size_mult - 1); |
362 | { | 609 | capacity_data->block_size = htobe32(block_size*block_size_mult); |
363 | capacity_data->block_count = htobe32(cinfo->numblocks - 1); | 610 | |
364 | capacity_data->block_size = htobe32(cinfo->blocksize); | 611 | send_command_result(capacity_data, MIN(sizeof(struct capacity), length)); |
365 | } | ||
366 | else | ||
367 | { | ||
368 | capacity_data->block_count = htobe32(0); | ||
369 | capacity_data->block_size = htobe32(0); | ||
370 | } | ||
371 | #else | ||
372 | unsigned short* identify = ata_get_identify(); | ||
373 | /* Careful : "block count" actually means the number of the last block */ | ||
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); | ||
376 | #endif | ||
377 | usb_drv_send(EP_TX, capacity_data, | ||
378 | MIN(sizeof _capacity_data, length)); | ||
379 | send_csw(cbw->tag, SCSI_STATUS_GOOD); | ||
380 | break; | 612 | break; |
381 | } | 613 | } |
382 | 614 | ||
383 | case SCSI_READ_10: | 615 | case SCSI_READ_10: |
616 | logf("scsi read10 %d",lun); | ||
617 | if(! lun_present) { | ||
618 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
619 | cur_sense_data.sense_key=SENSE_NOT_READY; | ||
620 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | ||
621 | break; | ||
622 | } | ||
623 | trigger_cpu_boost(); | ||
624 | current_cmd.data[0] = transfer_buffer; | ||
625 | current_cmd.data[1] = &transfer_buffer[BUFFER_SIZE]; | ||
626 | current_cmd.data_select=0; | ||
384 | current_cmd.sector = block_size_mult * | 627 | current_cmd.sector = block_size_mult * |
385 | (cbw->command_block[2] << 24 | | 628 | (cbw->command_block[2] << 24 | |
386 | cbw->command_block[3] << 16 | | 629 | cbw->command_block[3] << 16 | |
@@ -389,32 +632,35 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
389 | current_cmd.count = block_size_mult * | 632 | current_cmd.count = block_size_mult * |
390 | (cbw->command_block[7] << 16 | | 633 | (cbw->command_block[7] << 16 | |
391 | cbw->command_block[8]); | 634 | cbw->command_block[8]); |
392 | current_cmd.tag = cbw->tag; | ||
393 | current_cmd.lun = cbw->lun; | ||
394 | 635 | ||
395 | //logf("scsi read %d %d", current_cmd.sector, current_cmd.count); | 636 | logf("scsi read %d %d", current_cmd.sector, current_cmd.count); |
396 | 637 | ||
397 | //logf("Asked for %d sectors",current_cmd.count); | 638 | if((current_cmd.sector + current_cmd.count) * block_size_mult > block_count) { |
398 | if(current_cmd.count > sectors_per_transfer) | 639 | send_csw(SCSI_STATUS_CHECK_CONDITION); |
399 | { | 640 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; |
400 | current_cmd.count = sectors_per_transfer; | 641 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; |
401 | } | ||
402 | //logf("Sending %d sectors",current_cmd.count); | ||
403 | |||
404 | if(current_cmd.count*block_size > sizeof(_transfer_buffer)) { | ||
405 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | ||
406 | } | 642 | } |
407 | else { | 643 | else { |
408 | ata_read_sectors(IF_MV2(lun,) current_cmd.sector, | 644 | /* TODO: any way to do this nonblocking ? */ |
409 | current_cmd.count, transfer_buffer); | 645 | current_cmd.last_result = ata_read_sectors(IF_MV2(current_cmd.lun,) current_cmd.sector, |
410 | usb_drv_send(EP_TX, transfer_buffer, | 646 | MIN(BUFFER_SIZE/SECTOR_SIZE,current_cmd.count), |
411 | current_cmd.count*block_size); | 647 | current_cmd.data[current_cmd.data_select]); |
412 | send_csw(current_cmd.tag, SCSI_STATUS_GOOD); | 648 | send_and_read_next(); |
413 | } | 649 | } |
414 | break; | 650 | break; |
415 | 651 | ||
416 | case SCSI_WRITE_10: | 652 | case SCSI_WRITE_10: |
417 | //logf("scsi write10"); | 653 | logf("scsi write10 %d",lun); |
654 | if(! lun_present) { | ||
655 | send_csw(SCSI_STATUS_CHECK_CONDITION); | ||
656 | cur_sense_data.sense_key=SENSE_NOT_READY; | ||
657 | cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; | ||
658 | break; | ||
659 | } | ||
660 | trigger_cpu_boost(); | ||
661 | current_cmd.data[0] = transfer_buffer; | ||
662 | current_cmd.data[1] = &transfer_buffer[BUFFER_SIZE]; | ||
663 | current_cmd.data_select=0; | ||
418 | current_cmd.sector = block_size_mult * | 664 | current_cmd.sector = block_size_mult * |
419 | (cbw->command_block[2] << 24 | | 665 | (cbw->command_block[2] << 24 | |
420 | cbw->command_block[3] << 16 | | 666 | cbw->command_block[3] << 16 | |
@@ -423,53 +669,74 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
423 | current_cmd.count = block_size_mult * | 669 | current_cmd.count = block_size_mult * |
424 | (cbw->command_block[7] << 16 | | 670 | (cbw->command_block[7] << 16 | |
425 | cbw->command_block[8]); | 671 | cbw->command_block[8]); |
426 | current_cmd.tag = cbw->tag; | ||
427 | current_cmd.lun = cbw->lun; | ||
428 | /* expect data */ | 672 | /* expect data */ |
429 | if(current_cmd.count*block_size > sizeof(_transfer_buffer)) { | 673 | if((current_cmd.sector + current_cmd.count) * block_size_mult > block_count) { |
430 | send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION); | 674 | send_csw(SCSI_STATUS_CHECK_CONDITION); |
675 | cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST; | ||
676 | cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE; | ||
431 | } | 677 | } |
432 | else { | 678 | else { |
433 | usb_drv_recv(EP_RX, transfer_buffer, | 679 | receive_block_data(current_cmd.data[0], |
434 | current_cmd.count*block_size); | 680 | MIN(BUFFER_SIZE,current_cmd.count*SECTOR_SIZE)); |
435 | state = RECEIVING; | ||
436 | } | 681 | } |
437 | 682 | ||
438 | break; | 683 | break; |
439 | 684 | ||
440 | default: | 685 | default: |
441 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); | 686 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); |
442 | usb_drv_stall(EP_TX, true); | 687 | usb_drv_stall(EP_MASS_STORAGE, true,true); |
443 | send_csw(current_cmd.tag, SCSI_STATUS_GOOD); | 688 | send_csw(SCSI_STATUS_GOOD); |
444 | break; | 689 | break; |
445 | } | 690 | } |
446 | } | 691 | } |
447 | 692 | ||
448 | static void send_csw(unsigned int tag, int status) | 693 | static void send_block_data(void *data,int size) |
694 | { | ||
695 | usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); | ||
696 | state = SENDING_BLOCKS; | ||
697 | } | ||
698 | |||
699 | static void send_command_result(void *data,int size) | ||
700 | { | ||
701 | usb_drv_send_nonblocking(EP_MASS_STORAGE, data,size); | ||
702 | state = SENDING_RESULT; | ||
703 | } | ||
704 | |||
705 | static void receive_block_data(void *data,int size) | ||
449 | { | 706 | { |
450 | static struct command_status_wrapper _csw; | 707 | usb_drv_recv(EP_MASS_STORAGE, data, size); |
451 | struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw); | 708 | state = RECEIVING_BLOCKS; |
709 | } | ||
710 | |||
711 | static void send_csw(int status) | ||
712 | { | ||
713 | cancel_cpu_boost(); | ||
452 | csw->signature = CSW_SIGNATURE; | 714 | csw->signature = CSW_SIGNATURE; |
453 | csw->tag = tag; | 715 | csw->tag = current_cmd.tag; |
454 | csw->data_residue = 0; | 716 | csw->data_residue = 0; |
455 | csw->status = status; | 717 | csw->status = status; |
456 | 718 | ||
457 | //logf("csw %x %x", csw->tag, csw->signature); | 719 | usb_drv_send_nonblocking(EP_MASS_STORAGE, csw, sizeof(struct command_status_wrapper)); |
458 | usb_drv_send(EP_TX, csw, sizeof _csw); | 720 | state = SENDING_CSW; |
721 | logf("CSW: %X",status); | ||
722 | |||
723 | if(status == SCSI_STATUS_GOOD) { | ||
724 | cur_sense_data.sense_key=0; | ||
725 | cur_sense_data.information=0; | ||
726 | cur_sense_data.asc=0; | ||
727 | } | ||
459 | } | 728 | } |
460 | 729 | ||
461 | /* convert ATA IDENTIFY to SCSI INQUIRY */ | 730 | /* convert ATA IDENTIFY to SCSI INQUIRY */ |
462 | static void identify2inquiry(int lun) | 731 | static void identify2inquiry(int lun) |
463 | { | 732 | { |
464 | #ifdef HAVE_FLASH_STORAGE | 733 | #ifdef HAVE_FLASH_STORAGE |
465 | if(lun==0) | 734 | if(lun==0) { |
466 | { | ||
467 | memcpy(&inquiry->VendorId,"Rockbox ",8); | 735 | memcpy(&inquiry->VendorId,"Rockbox ",8); |
468 | memcpy(&inquiry->ProductId,"Internal Storage",16); | 736 | memcpy(&inquiry->ProductId,"Internal Storage",16); |
469 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); | 737 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); |
470 | } | 738 | } |
471 | else | 739 | else { |
472 | { | ||
473 | memcpy(&inquiry->VendorId,"Rockbox ",8); | 740 | memcpy(&inquiry->VendorId,"Rockbox ",8); |
474 | memcpy(&inquiry->ProductId,"SD Card Slot ",16); | 741 | memcpy(&inquiry->ProductId,"SD Card Slot ",16); |
475 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); | 742 | memcpy(&inquiry->ProductRevisionLevel,"0.00",4); |
@@ -480,7 +747,7 @@ static void identify2inquiry(int lun) | |||
480 | unsigned short* src; | 747 | unsigned short* src; |
481 | unsigned short* identify = ata_get_identify(); | 748 | unsigned short* identify = ata_get_identify(); |
482 | (void)lun; | 749 | (void)lun; |
483 | memset(inquiry, 0, sizeof _inquiry); | 750 | memset(inquiry, 0, sizeof(struct inquiry_data)); |
484 | 751 | ||
485 | if (identify[82] & 4) | 752 | if (identify[82] & 4) |
486 | inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | 753 | inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; |
@@ -501,8 +768,8 @@ static void identify2inquiry(int lun) | |||
501 | 768 | ||
502 | inquiry->DeviceType = DIRECT_ACCESS_DEVICE; | 769 | inquiry->DeviceType = DIRECT_ACCESS_DEVICE; |
503 | inquiry->AdditionalLength = 0x1f; | 770 | inquiry->AdditionalLength = 0x1f; |
504 | inquiry->Versions = 3; /* ANSI SCSI level 2 */ | 771 | inquiry->Versions = 4; /* SPC-2 */ |
505 | inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */ | 772 | inquiry->Format = 2; /* SPC-2/3 inquiry format */ |
506 | 773 | ||
507 | #ifdef HAVE_HOTSWAP | 774 | #ifdef HAVE_HOTSWAP |
508 | inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; | 775 | inquiry->DeviceTypeModifier = DEVICE_REMOVABLE; |
@@ -510,3 +777,4 @@ static void identify2inquiry(int lun) | |||
510 | 777 | ||
511 | } | 778 | } |
512 | 779 | ||
780 | #endif /* USB_STORAGE */ | ||