blob: fd6517a5e3d78620c5fb321771512cb836634c2b [file] [log] [blame]
Patrick Georgid21f68b2008-09-02 16:06:22 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <arch/endian.h>
Jordan Crouse29061a52008-09-11 17:29:00 +000031#include <usb/usb.h>
32#include <usb/usbmsc.h>
33#include <usb/usbdisk.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000034
35enum {
36 msc_subclass_rbc = 0x1,
37 msc_subclass_mmc2 = 0x2,
38 msc_subclass_qic157 = 0x3,
39 msc_subclass_ufi = 0x4,
40 msc_subclass_sff8070i = 0x5,
41 msc_subclass_scsitrans = 0x6
42};
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000043
Patrick Georgid21f68b2008-09-02 16:06:22 +000044static const char *msc_subclass_strings[7] = {
45 "(none)",
46 "RBC",
47 "MMC-2",
48 "QIC-157",
49 "UFI",
50 "SFF-8070i",
51 "SCSI transparent"
52};
53enum {
54 msc_proto_cbi_wcomp = 0x0,
55 msc_proto_cbi_wocomp = 0x1,
56 msc_proto_bulk_only = 0x50
57};
58static const char *msc_protocol_strings[0x51] = {
59 "Control/Bulk/Interrupt protocol (with command completion interrupt)",
60 "Control/Bulk/Interrupt protocol (with no command completion interrupt)",
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66 "Bulk-Only Transport"
67};
68
69
70static void
71usb_msc_destroy (usbdev_t *dev)
72{
Patrick Georgi4727c072008-10-16 19:20:51 +000073 if (usbdisk_remove)
74 usbdisk_remove (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +000075 free (dev->data);
76 dev->data = 0;
77}
78
79static void
80usb_msc_poll (usbdev_t *dev)
81{
82}
83
84const int DEV_RESET = 0xff;
85const int GET_MAX_LUN = 0xfe;
86
87const unsigned int cbw_signature = 0x43425355;
88const unsigned int csw_signature = 0x53425355;
89
90typedef struct {
91 unsigned int dCBWSignature;
92 unsigned int dCBWTag;
93 unsigned int dCBWDataTransferLength;
94 unsigned char bmCBWFlags;
95 unsigned long bCBWLUN:4;
96 unsigned long:4;
97 unsigned long bCBWCBLength:5;
98 unsigned long:3;
99 unsigned char CBWCB[31 - 15];
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000100} __attribute__ ((packed)) cbw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000101
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000102typedef struct {
103 unsigned int dCSWSignature;
104 unsigned int dCSWTag;
105 unsigned int dCSWDataResidue;
106 unsigned char bCSWStatus;
107} __attribute__ ((packed)) csw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000108
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000109static int
110request_sense (usbdev_t *dev);
111
112static void
113reset_transport (usbdev_t *dev)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000114{
115 dev_req_t dr;
116 memset (&dr, 0, sizeof (dr));
117 dr.bmRequestType = 0;
118 dr.data_dir = host_to_device;
119#ifndef QEMU
120 dr.req_type = class_type;
121 dr.req_recp = iface_recp;
122#endif
123 dr.bRequest = DEV_RESET;
124 dr.wValue = 0;
125 dr.wIndex = 0;
126 dr.wLength = 0;
127 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
128 clear_stall (MSC_INST (dev)->bulk_in);
129 clear_stall (MSC_INST (dev)->bulk_out);
130}
131
132/* device may stall this command, so beware! */
133static int
134get_max_luns (usbdev_t *dev)
135{
136 unsigned char luns = 75;
137 dev_req_t dr;
138 dr.bmRequestType = 0;
139 dr.data_dir = device_to_host;
140#ifndef QEMU
141 dr.req_type = class_type;
142 dr.req_recp = iface_recp;
143#endif
144 dr.bRequest = GET_MAX_LUN;
145 dr.wValue = 0;
146 dr.wIndex = 0;
147 dr.wLength = 1;
148 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
149 luns = 0; // assume only 1 lun if req fails
150 }
151 return luns;
152}
153
Nico Huber43b9f322012-05-21 14:05:41 +0200154unsigned int tag;
155unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000156
157static void
158wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
159 int cmdlen)
160{
161 memset (cbw, 0, sizeof (cbw_t));
162
163 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200164 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000165 cbw->bCBWLUN = lun; // static value per device
166
167 cbw->dCBWDataTransferLength = datalen;
168 cbw->bmCBWFlags = dir;
169 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
170 cbw->bCBWCBLength = cmdlen;
171}
172
Nico Huber43b9f322012-05-21 14:05:41 +0200173static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000174get_csw (endpoint_t *ep, csw_t *csw)
175{
Nico Huber43b9f322012-05-21 14:05:41 +0200176 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000177 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200178 if (ep->dev->controller->bulk
179 (ep, sizeof (csw_t), (u8 *) csw, 1)) {
180 reset_transport (ep->dev);
181 return 1;
182 }
183 }
184 if (csw->dCSWTag != tag) {
185 reset_transport (ep->dev);
186 return 1;
187 }
188 return 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000189}
190
191static int
192execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
193 u8 *buf, int buflen)
194{
195 cbw_t cbw;
196 csw_t csw;
197
198 int always_succeed = 0;
199 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
200 always_succeed = 1;
201 }
202 wrap_cbw (&cbw, buflen, dir, cb, cblen);
203 if (dev->controller->
204 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000205 reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000206 return 1;
207 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000208 if (buflen > 0) {
209 if (dir == cbw_direction_data_in) {
210 if (dev->controller->
211 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
212 clear_stall (MSC_INST (dev)->bulk_in);
213 return 1;
214 }
215 } else {
216 if (dev->controller->
217 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
218 clear_stall (MSC_INST (dev)->bulk_out);
219 return 1;
220 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000221 }
222 }
Nico Huber43b9f322012-05-21 14:05:41 +0200223 if (get_csw (MSC_INST (dev)->bulk_in, &csw))
224 return 1;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000225 if (always_succeed == 1) {
226 // return success, regardless of message
227 return 0;
228 }
229 if (csw.bCSWStatus == 2) {
230 // phase error, reset transport
231 reset_transport (dev);
232 return 1;
233 }
234 if (csw.bCSWStatus == 0) {
235 // no error, exit
236 return 0;
237 }
Nico Huber43b9f322012-05-21 14:05:41 +0200238 if (cb[0] != 0x03) /* 0x03 == request sense */
239 // error "check condition" or reserved error
240 request_sense (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000241 return 1;
242}
243
244typedef struct {
245 unsigned char command; //0
246 unsigned char res1; //1
247 unsigned int block; //2-5
248 unsigned char res2; //6
249 unsigned short numblocks; //7-8
250 unsigned char res3; //9 - the block is 10 bytes long
251} __attribute__ ((packed)) cmdblock_t;
252
253typedef struct {
254 unsigned char command; //0
255 unsigned char res1; //1
256 unsigned char res2; //2
257 unsigned char res3; //3
258 unsigned char lun; //4
259 unsigned char res4; //5
260} __attribute__ ((packed)) cmdblock6_t;
261
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000262/**
263 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
264 * start and count from 512b units.
265 * Start and count must be aligned so that they match the native
266 * sector size.
267 *
268 * @param dev device to access
269 * @param start first sector to access
270 * @param n number of sectors to access
271 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
272 * @param buf buffer to read into or write from. Must be at least n*512 bytes
273 * @return 0 on success, 1 on failure
274 */
275int
276readwrite_blocks_512 (usbdev_t *dev, int start, int n,
277 cbw_direction dir, u8 *buf)
278{
279 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
280 return readwrite_blocks (dev, start / blocksize_divider,
281 n / blocksize_divider, dir, buf);
282}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000283
284/**
285 * Reads or writes a number of sequential blocks on a USB storage device.
286 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
287 * of at most 2TB. It assumes sectors of 512 bytes.
288 *
289 * @param dev device to access
290 * @param start first sector to access
291 * @param n number of sectors to access
292 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000293 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000294 * @return 0 on success, 1 on failure
295 */
296int
297readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
298{
299 cmdblock_t cb;
300 memset (&cb, 0, sizeof (cb));
301 if (dir == cbw_direction_data_in) {
302 // read
303 cb.command = 0x28;
304 } else {
305 // write
306 cb.command = 0x2a;
307 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000308 cb.block = htonl (start);
309 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000310
Patrick Georgid21f68b2008-09-02 16:06:22 +0000311 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000312 n * MSC_INST(dev)->blocksize);
313}
314
315/* Only request it, we don't interpret it.
316 On certain errors, that's necessary to get devices out of
317 a special state called "Contingent Allegiance Condition" */
318static int
319request_sense (usbdev_t *dev)
320{
321 u8 buf[19];
322 cmdblock6_t cb;
323 memset (&cb, 0, sizeof (cb));
324 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000325
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000326 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
327 sizeof (cb), buf, 19);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000328}
329
330static int
331test_unit_ready (usbdev_t *dev)
332{
333 cmdblock6_t cb;
334 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
335 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
336 sizeof (cb), 0, 0);
337}
338
339static int
340spin_up (usbdev_t *dev)
341{
342 cmdblock6_t cb;
343 memset (&cb, 0, sizeof (cb));
344 cb.command = 0x1b;
345 cb.lun = 1;
346 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
347 sizeof (cb), 0, 0);
348}
349
350static void
351read_capacity (usbdev_t *dev)
352{
353 cmdblock_t cb;
354 memset (&cb, 0, sizeof (cb));
355 cb.command = 0x25; // read capacity
356 u8 buf[8];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000357
Mathias Krausec4716b42011-06-08 15:36:55 +0200358 debug ("Reading capacity of mass storage device.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000359 int count = 0;
360 while ((count++ < 20)
361 &&
362 (execute_command
363 (dev, cbw_direction_data_in, (u8 *) &cb, sizeof (cb), buf,
364 8) == 1));
365 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000366 // still not successful, assume 2tb in 512byte sectors, which is just the same garbage as any other number, but probably more usable.
Mathias Krausec4716b42011-06-08 15:36:55 +0200367 printf (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000368 MSC_INST (dev)->numblocks = 0xffffffff;
369 MSC_INST (dev)->blocksize = 512;
370 } else {
371 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
372 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
373 }
Mathias Krausec4716b42011-06-08 15:36:55 +0200374 printf (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
375 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200376 /* round down high block counts to avoid integer overflow */
377 MSC_INST (dev)->numblocks > 1000000
378 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200379 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000380}
381
382void
383usb_msc_init (usbdev_t *dev)
384{
385 int i, timeout;
386
387 dev->destroy = usb_msc_destroy;
388 dev->poll = usb_msc_poll;
389
390 configuration_descriptor_t *cd =
391 (configuration_descriptor_t *) dev->configuration;
392 interface_descriptor_t *interface =
393 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
394
Mathias Krausec4716b42011-06-08 15:36:55 +0200395 debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000396 msc_subclass_strings[interface->bInterfaceSubClass]);
Mathias Krausec4716b42011-06-08 15:36:55 +0200397 debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000398 msc_protocol_strings[interface->bInterfaceProtocol]);
399
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000400
401 if (interface->bInterfaceProtocol != 0x50) {
402 printf (" Protocol not supported.\n");
403 return;
404 }
405
406 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
407 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
408 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000409 /* Other protocols, such as ATAPI don't seem to be very popular. looks like ATAPI would be really easy to add, if necessary. */
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000410 printf (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000411 return;
412 }
413
414 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000415 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100416 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000417
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000418 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000419 MSC_INST (dev)->bulk_in = 0;
420 MSC_INST (dev)->bulk_out = 0;
421
422 for (i = 1; i <= dev->num_endp; i++) {
423 if (dev->endpoints[i].endpoint == 0)
424 continue;
425 if (dev->endpoints[i].type != BULK)
426 continue;
427 if ((dev->endpoints[i].direction == IN)
428 && (MSC_INST (dev)->bulk_in == 0))
429 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
430 if ((dev->endpoints[i].direction == OUT)
431 && (MSC_INST (dev)->bulk_out == 0))
432 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
433 }
434
435 if (MSC_INST (dev)->bulk_in == 0)
436 fatal ("couldn't find bulk-in endpoint");
437 if (MSC_INST (dev)->bulk_out == 0)
438 fatal ("couldn't find bulk-out endpoint");
Mathias Krausec4716b42011-06-08 15:36:55 +0200439 debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000440 MSC_INST (dev)->bulk_in->endpoint,
441 MSC_INST (dev)->bulk_out->endpoint);
442
Mathias Krausec4716b42011-06-08 15:36:55 +0200443 debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000444
Mathias Krausec4716b42011-06-08 15:36:55 +0200445 printf (" Waiting for device to become ready...");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000446 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000447 while (test_unit_ready (dev) && --timeout) {
448 mdelay (100);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000449 if (!(timeout % 10))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000450 printf (".");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000451 }
452 if (test_unit_ready (dev)) {
453 printf ("timeout. Device not ready. Still trying...\n");
454 } else {
455 printf ("ok.\n");
456 }
457
Mathias Krausec4716b42011-06-08 15:36:55 +0200458 debug (" spin up");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000459 for (i = 0; i < 30; i++) {
Mathias Krausec4716b42011-06-08 15:36:55 +0200460 debug (".");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000461 if (!spin_up (dev)) {
Mathias Krausec4716b42011-06-08 15:36:55 +0200462 debug (" OK.");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000463 break;
464 }
465 mdelay (100);
466 }
Mathias Krausec4716b42011-06-08 15:36:55 +0200467 debug ("\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000468
469 read_capacity (dev);
Patrick Georgi4727c072008-10-16 19:20:51 +0000470 if (usbdisk_create)
471 usbdisk_create (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000472}