summaryrefslogtreecommitdiff
path: root/firmware/usbstack
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack')
-rw-r--r--firmware/usbstack/usb_core.c339
-rw-r--r--firmware/usbstack/usb_storage.c316
2 files changed, 492 insertions, 163 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 7e86086dd4..13993f9271 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -23,10 +23,17 @@
23//#define LOGF_ENABLE 23//#define LOGF_ENABLE
24#include "logf.h" 24#include "logf.h"
25 25
26//#define USB_STORAGE 26#ifndef BOOTLOADER
27//#define USB_SERIAL 27//#define USB_SERIAL
28//#define USB_BENCHMARK 28//#define USB_BENCHMARK
29#ifdef USE_ROCKBOX_USB
30#define USB_STORAGE
31#else
29#define USB_CHARGING_ONLY 32#define USB_CHARGING_ONLY
33#endif /* USE_ROCKBOX_USB */
34#else
35#define USB_CHARGING_ONLY
36#endif
30 37
31#include "usb_ch9.h" 38#include "usb_ch9.h"
32#include "usb_drv.h" 39#include "usb_drv.h"
@@ -63,21 +70,21 @@ static const struct usb_device_descriptor device_descriptor = {
63 .bcdDevice = 0x0100, 70 .bcdDevice = 0x0100,
64 .iManufacturer = 1, 71 .iManufacturer = 1,
65 .iProduct = 2, 72 .iProduct = 2,
66 .iSerialNumber = 0, 73 .iSerialNumber = 3,
67 .bNumConfigurations = 1 74 .bNumConfigurations = 1
68}; 75};
69 76
70static const struct { 77static const struct {
71 struct usb_config_descriptor config_descriptor; 78 struct usb_config_descriptor config_descriptor;
72 struct usb_interface_descriptor interface_descriptor; 79 struct usb_interface_descriptor interface_descriptor;
73 struct usb_endpoint_descriptor ep1_hs_in_descriptor; 80 struct usb_endpoint_descriptor ep1_in_descriptor;
74 struct usb_endpoint_descriptor ep1_hs_out_descriptor; 81 struct usb_endpoint_descriptor ep1_out_descriptor;
75} config_data = 82} config_data_fs =
76{ 83{
77 { 84 {
78 .bLength = sizeof(struct usb_config_descriptor), 85 .bLength = sizeof(struct usb_config_descriptor),
79 .bDescriptorType = USB_DT_CONFIG, 86 .bDescriptorType = USB_DT_CONFIG,
80 .wTotalLength = sizeof config_data, 87 .wTotalLength = sizeof config_data_fs,
81 .bNumInterfaces = 1, 88 .bNumInterfaces = 1,
82 .bConfigurationValue = 1, 89 .bConfigurationValue = 1,
83 .iConfiguration = 0, 90 .iConfiguration = 0,
@@ -96,12 +103,153 @@ static const struct {
96 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 103 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
97 .bInterfaceSubClass = 0, 104 .bInterfaceSubClass = 0,
98 .bInterfaceProtocol = 0, 105 .bInterfaceProtocol = 0,
106 .iInterface = 5
107 },
108
109 {
110 .bLength = sizeof(struct usb_endpoint_descriptor),
111 .bDescriptorType = USB_DT_ENDPOINT,
112 .bEndpointAddress = EP_TX | USB_DIR_IN,
113 .bmAttributes = USB_ENDPOINT_XFER_BULK,
114 .wMaxPacketSize = 512,
115 .bInterval = 0
116 },
117 {
118 .bLength = sizeof(struct usb_endpoint_descriptor),
119 .bDescriptorType = USB_DT_ENDPOINT,
120 .bEndpointAddress = EP_RX | USB_DIR_OUT,
121 .bmAttributes = USB_ENDPOINT_XFER_BULK,
122 .wMaxPacketSize = 512,
123 .bInterval = 0
124 }
125#endif
126
127#ifdef USB_STORAGE
128 /* storage interface */
129 {
130 .bLength = sizeof(struct usb_interface_descriptor),
131 .bDescriptorType = USB_DT_INTERFACE,
132 .bInterfaceNumber = 0,
133 .bAlternateSetting = 0,
134 .bNumEndpoints = 2,
135 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
136 .bInterfaceSubClass = USB_SC_SCSI,
137 .bInterfaceProtocol = USB_PROT_BULK,
138 .iInterface = 0
139 },
140
141 {
142 .bLength = sizeof(struct usb_endpoint_descriptor),
143 .bDescriptorType = USB_DT_ENDPOINT,
144 .bEndpointAddress = EP_TX | USB_DIR_IN,
145 .bmAttributes = USB_ENDPOINT_XFER_BULK,
146 .wMaxPacketSize = 16,
147 .bInterval = 0
148 },
149 {
150 .bLength = sizeof(struct usb_endpoint_descriptor),
151 .bDescriptorType = USB_DT_ENDPOINT,
152 .bEndpointAddress = EP_RX | USB_DIR_OUT,
153 .bmAttributes = USB_ENDPOINT_XFER_BULK,
154 .wMaxPacketSize = 16,
155 .bInterval = 0
156 }
157#endif
158
159#ifdef USB_SERIAL
160 /* serial interface */
161 {
162 .bLength = sizeof(struct usb_interface_descriptor),
163 .bDescriptorType = USB_DT_INTERFACE,
164 .bInterfaceNumber = 0,
165 .bAlternateSetting = 0,
166 .bNumEndpoints = 2,
167 .bInterfaceClass = USB_CLASS_CDC_DATA,
168 .bInterfaceSubClass = 0,
169 .bInterfaceProtocol = 0,
170 .iInterface = 0
171 },
172
173 {
174 .bLength = sizeof(struct usb_endpoint_descriptor),
175 .bDescriptorType = USB_DT_ENDPOINT,
176 .bEndpointAddress = EP_TX | USB_DIR_IN,
177 .bmAttributes = USB_ENDPOINT_XFER_BULK,
178 .wMaxPacketSize = 64,
179 .bInterval = 0
180 },
181 {
182 .bLength = sizeof(struct usb_endpoint_descriptor),
183 .bDescriptorType = USB_DT_ENDPOINT,
184 .bEndpointAddress = EP_RX | USB_DIR_OUT,
185 .bmAttributes = USB_ENDPOINT_XFER_BULK,
186 .wMaxPacketSize = 64,
187 .bInterval = 0
188 }
189#endif
190
191#ifdef USB_BENCHMARK
192 /* bulk test interface */
193 {
194 .bLength = sizeof(struct usb_interface_descriptor),
195 .bDescriptorType = USB_DT_INTERFACE,
196 .bInterfaceNumber = 0,
197 .bAlternateSetting = 0,
198 .bNumEndpoints = 2,
199 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
200 .bInterfaceSubClass = 255,
201 .bInterfaceProtocol = 255,
99 .iInterface = 4 202 .iInterface = 4
100 }, 203 },
101 204
102 { 205 {
103 .bLength = sizeof(struct usb_endpoint_descriptor), 206 .bLength = sizeof(struct usb_endpoint_descriptor),
104 .bDescriptorType = USB_DT_ENDPOINT, 207 .bDescriptorType = USB_DT_ENDPOINT,
208 .bEndpointAddress = EP_RX | USB_DIR_OUT,
209 .bmAttributes = USB_ENDPOINT_XFER_BULK,
210 .wMaxPacketSize = 64,
211 .bInterval = 0
212 },
213 {
214 .bLength = sizeof(struct usb_endpoint_descriptor),
215 .bDescriptorType = USB_DT_ENDPOINT,
216 .bEndpointAddress = EP_TX | USB_DIR_IN,
217 .bmAttributes = USB_ENDPOINT_XFER_BULK,
218 .wMaxPacketSize = 64,
219 .bInterval = 0
220 }
221#endif
222},
223config_data_hs =
224{
225 {
226 .bLength = sizeof(struct usb_config_descriptor),
227 .bDescriptorType = USB_DT_CONFIG,
228 .wTotalLength = sizeof config_data_hs,
229 .bNumInterfaces = 1,
230 .bConfigurationValue = 1,
231 .iConfiguration = 0,
232 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
233 .bMaxPower = 250, /* 500mA in 2mA units */
234 },
235
236#ifdef USB_CHARGING_ONLY
237 /* dummy interface for charging-only */
238 {
239 .bLength = sizeof(struct usb_interface_descriptor),
240 .bDescriptorType = USB_DT_INTERFACE,
241 .bInterfaceNumber = 0,
242 .bAlternateSetting = 0,
243 .bNumEndpoints = 2,
244 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
245 .bInterfaceSubClass = 0,
246 .bInterfaceProtocol = 0,
247 .iInterface = 5
248 },
249
250 {
251 .bLength = sizeof(struct usb_endpoint_descriptor),
252 .bDescriptorType = USB_DT_ENDPOINT,
105 .bEndpointAddress = EP_TX | USB_DIR_IN, 253 .bEndpointAddress = EP_TX | USB_DIR_IN,
106 .bmAttributes = USB_ENDPOINT_XFER_BULK, 254 .bmAttributes = USB_ENDPOINT_XFER_BULK,
107 .wMaxPacketSize = 512, 255 .wMaxPacketSize = 512,
@@ -168,7 +316,7 @@ static const struct {
168 .bDescriptorType = USB_DT_ENDPOINT, 316 .bDescriptorType = USB_DT_ENDPOINT,
169 .bEndpointAddress = EP_TX | USB_DIR_IN, 317 .bEndpointAddress = EP_TX | USB_DIR_IN,
170 .bmAttributes = USB_ENDPOINT_XFER_BULK, 318 .bmAttributes = USB_ENDPOINT_XFER_BULK,
171 .wMaxPacketSize = 64, 319 .wMaxPacketSize = 512,
172 .bInterval = 0 320 .bInterval = 0
173 }, 321 },
174 { 322 {
@@ -176,7 +324,7 @@ static const struct {
176 .bDescriptorType = USB_DT_ENDPOINT, 324 .bDescriptorType = USB_DT_ENDPOINT,
177 .bEndpointAddress = EP_RX | USB_DIR_OUT, 325 .bEndpointAddress = EP_RX | USB_DIR_OUT,
178 .bmAttributes = USB_ENDPOINT_XFER_BULK, 326 .bmAttributes = USB_ENDPOINT_XFER_BULK,
179 .wMaxPacketSize = 64, 327 .wMaxPacketSize = 512,
180 .bInterval = 0 328 .bInterval = 0
181 } 329 }
182#endif 330#endif
@@ -192,7 +340,7 @@ static const struct {
192 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 340 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
193 .bInterfaceSubClass = 255, 341 .bInterfaceSubClass = 255,
194 .bInterfaceProtocol = 255, 342 .bInterfaceProtocol = 255,
195 .iInterface = 3 343 .iInterface = 4
196 }, 344 },
197 345
198 { 346 {
@@ -200,7 +348,6 @@ static const struct {
200 .bDescriptorType = USB_DT_ENDPOINT, 348 .bDescriptorType = USB_DT_ENDPOINT,
201 .bEndpointAddress = EP_RX | USB_DIR_OUT, 349 .bEndpointAddress = EP_RX | USB_DIR_OUT,
202 .bmAttributes = USB_ENDPOINT_XFER_BULK, 350 .bmAttributes = USB_ENDPOINT_XFER_BULK,
203// .wMaxPacketSize = 64,
204 .wMaxPacketSize = 512, 351 .wMaxPacketSize = 512,
205 .bInterval = 0 352 .bInterval = 0
206 }, 353 },
@@ -209,7 +356,6 @@ static const struct {
209 .bDescriptorType = USB_DT_ENDPOINT, 356 .bDescriptorType = USB_DT_ENDPOINT,
210 .bEndpointAddress = EP_TX | USB_DIR_IN, 357 .bEndpointAddress = EP_TX | USB_DIR_IN,
211 .bmAttributes = USB_ENDPOINT_XFER_BULK, 358 .bmAttributes = USB_ENDPOINT_XFER_BULK,
212// .wMaxPacketSize = 64,
213 .wMaxPacketSize = 512, 359 .wMaxPacketSize = 512,
214 .bInterval = 0 360 .bInterval = 0
215 } 361 }
@@ -228,72 +374,61 @@ static const struct usb_qualifier_descriptor qualifier_descriptor =
228 .bNumConfigurations = 1 374 .bNumConfigurations = 1
229}; 375};
230 376
231/* full speed = 12 Mbit */ 377static struct usb_string_descriptor usb_string_iManufacturer =
232static const struct usb_endpoint_descriptor ep1_fs_in_descriptor =
233{ 378{
234 .bLength = sizeof(struct usb_endpoint_descriptor), 379 24,
235 .bDescriptorType = USB_DT_ENDPOINT, 380 USB_DT_STRING,
236 .bEndpointAddress = 1 | USB_DIR_IN, 381 {'R','o','c','k','b','o','x','.','o','r','g'}
237 .bmAttributes = USB_ENDPOINT_XFER_BULK,
238 .wMaxPacketSize = 64,
239 .bInterval = 0
240}; 382};
241 383
242static const struct usb_endpoint_descriptor ep1_fs_out_descriptor = 384static struct usb_string_descriptor usb_string_iProduct =
243{ 385{
244 .bLength = sizeof(struct usb_endpoint_descriptor), 386 42,
245 .bDescriptorType = USB_DT_ENDPOINT, 387 USB_DT_STRING,
246 .bEndpointAddress = 1 | USB_DIR_OUT, 388 {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
247 .bmAttributes = USB_ENDPOINT_XFER_BULK,
248 .wMaxPacketSize = 64,
249 .bInterval = 0
250}; 389};
251 390
252static const struct usb_endpoint_descriptor* ep_descriptors[4] = 391static struct usb_string_descriptor usb_string_iSerial =
253{ 392{
254 &config_data.ep1_hs_in_descriptor, 393 34,
255 &config_data.ep1_hs_out_descriptor, 394 USB_DT_STRING,
256 &ep1_fs_in_descriptor, 395 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}
257 &ep1_fs_out_descriptor
258}; 396};
259 397
398
399/* Generic for all targets */
400
260/* this is stringid #0: languages supported */ 401/* this is stringid #0: languages supported */
261static const struct usb_string_descriptor lang_descriptor = 402static struct usb_string_descriptor lang_descriptor =
262{ 403{
263 sizeof(struct usb_string_descriptor), 404 4,
264 USB_DT_STRING, 405 USB_DT_STRING,
265 {0x0409} /* LANGID US English */ 406 {0x0409} /* LANGID US English */
266}; 407};
267 408
268/* this is stringid #1 and up: the actual strings */ 409static struct usb_string_descriptor usb_string_usb_benchmark =
269static const struct {
270 unsigned char size;
271 unsigned char type;
272 unsigned short string[32];
273} usb_strings[] =
274{ 410{
275 { 411 40,
276 24, 412 USB_DT_STRING,
277 USB_DT_STRING, 413 {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
278 {'R','o','c','k','b','o','x','.','o','r','g'}
279 },
280 {
281 42,
282 USB_DT_STRING,
283 {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'}
284 },
285 {
286 40,
287 USB_DT_STRING,
288 {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
289 },
290 {
291 28,
292 USB_DT_STRING,
293 {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
294 }
295}; 414};
296 415
416static struct usb_string_descriptor usb_string_charging_only =
417{
418 28,
419 USB_DT_STRING,
420 {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
421};
422
423static struct usb_string_descriptor* usb_strings[] =
424{
425 &lang_descriptor,
426 &usb_string_iManufacturer,
427 &usb_string_iProduct,
428 &usb_string_iSerial,
429 &usb_string_usb_benchmark,
430 &usb_string_charging_only
431};
297 432
298static int usb_address = 0; 433static int usb_address = 0;
299static bool initialized = false; 434static bool initialized = false;
@@ -310,11 +445,45 @@ static void usb_core_thread(void);
310 445
311static void ack_control(struct usb_ctrlrequest* req); 446static void ack_control(struct usb_ctrlrequest* req);
312 447
448#ifdef IPOD_ARCH
449void set_serial_descriptor(void)
450{
451 static short hex[16] = {'0','1','2','3','4','5','6','7',
452 '8','9','A','B','C','D','E','F'};
453#ifdef IPOD_VIDEO
454 uint32_t* serial = (uint32_t*)(0x20004034);
455#else
456 uint32_t* serial = (uint32_t*)(0x20002034);
457#endif
458
459 /* We need to convert from a little-endian 64-bit int
460 into a utf-16 string of hex characters */
461 short* p = &usb_string_iSerial.wString[15];
462 uint32_t x;
463 int i,j;
464
465 for (i = 0; i < 2; i++)
466 {
467 x = serial[i];
468 for (j=0;j<8;j++)
469 {
470 *p-- = hex[x & 0xf];
471 x >>= 4;
472 }
473 }
474
475}
476#endif
477
313void usb_core_init(void) 478void usb_core_init(void)
314{ 479{
315 if (initialized) 480 if (initialized)
316 return; 481 return;
317 482
483#ifdef IPOD_ARCH
484 set_serial_descriptor();
485#endif
486
318 queue_init(&usbcore_queue, false); 487 queue_init(&usbcore_queue, false);
319 usb_drv_init(); 488 usb_drv_init();
320#ifdef USB_STORAGE 489#ifdef USB_STORAGE
@@ -469,43 +638,25 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
469 break; 638 break;
470 639
471 case USB_DT_CONFIG: 640 case USB_DT_CONFIG:
472 ptr = &config_data; 641 if(usb_drv_port_speed())
473 size = sizeof config_data; 642 {
474 break; 643 ptr = &config_data_hs;
475 644 size = sizeof config_data_hs;
476 case USB_DT_STRING: 645 }
477 switch (index) { 646 else
478 case 0: /* lang descriptor */ 647 {
479 ptr = &lang_descriptor; 648 ptr = &config_data_fs;
480 size = sizeof lang_descriptor; 649 size = sizeof config_data_fs;
481 break;
482
483 default:
484 if ((unsigned)index <= (sizeof(usb_strings)/sizeof(usb_strings[0]))) {
485 index -= 1;
486 ptr = &usb_strings[index];
487 size = usb_strings[index].size;
488 }
489 else {
490 logf("bad string id %d", index);
491 usb_drv_stall(EP_CONTROL, true);
492 }
493 break;
494 } 650 }
495 break; 651 break;
496 652
497 case USB_DT_INTERFACE: 653 case USB_DT_STRING:
498 ptr = &config_data.interface_descriptor; 654 if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) {
499 size = sizeof config_data.interface_descriptor; 655 ptr = usb_strings[index];
500 break; 656 size = usb_strings[index]->bLength;
501
502 case USB_DT_ENDPOINT:
503 if (index <= NUM_ENDPOINTS) {
504 ptr = &ep_descriptors[index];
505 size = sizeof ep_descriptors[index];
506 } 657 }
507 else { 658 else {
508 logf("bad endpoint %d", index); 659 logf("bad string id %d", index);
509 usb_drv_stall(EP_CONTROL, true); 660 usb_drv_stall(EP_CONTROL, true);
510 } 661 }
511 break; 662 break;
@@ -515,12 +666,6 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
515 size = sizeof qualifier_descriptor; 666 size = sizeof qualifier_descriptor;
516 break; 667 break;
517 668
518/*
519 case USB_DT_OTHER_SPEED_CONFIG:
520 ptr = &other_speed_descriptor;
521 size = sizeof other_speed_descriptor;
522 break;
523*/
524 default: 669 default:
525 logf("bad desc %d", req->wValue >> 8); 670 logf("bad desc %d", req->wValue >> 8);
526 usb_drv_stall(EP_CONTROL, true); 671 usb_drv_stall(EP_CONTROL, true);
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
52struct inquiry_data { 59struct 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
72struct 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
65struct command_block_wrapper { 86struct 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
108struct 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 */
88static unsigned char _transfer_buffer[16384]; 115static unsigned char _transfer_buffer[16384*8] __attribute((aligned (4096)));
89static unsigned char* transfer_buffer; 116static unsigned char* transfer_buffer;
90static struct inquiry_data _inquiry; 117static struct inquiry_data _inquiry CACHEALIGN_ATTR;
91static struct inquiry_data* inquiry; 118static struct inquiry_data* inquiry;
92static struct capacity _capacity_data; 119static struct capacity _capacity_data CACHEALIGN_ATTR;
93static struct capacity* capacity_data; 120static struct capacity* capacity_data;
94 121static struct format_capacity _format_capacity_data CACHEALIGN_ATTR;
95//static unsigned char partial_sector[SECTOR_SIZE]; 122static struct format_capacity* format_capacity_data;
123static struct sense_data _sense_data CACHEALIGN_ATTR;
124static struct sense_data *sense_data;
96 125
97static struct { 126static 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); 133static void handle_scsi(struct command_block_wrapper* cbw);
105 void send_csw(unsigned int tag, int status); 134static void send_csw(unsigned int tag, int status);
106static void identify2inquiry(void); 135static void identify2inquiry(int lun);
107 136
108static enum { 137static 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
188void handle_scsi(struct command_block_wrapper* cbw) 244static 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
276void send_csw(unsigned int tag, int status) 448static 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 */
290static void identify2inquiry(void) 462static 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