blob: 8d5773629ffce9b6c29dbda52c06bc5786ea4a49 [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
154int tag;
155int lun = 0;
156
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;
164 cbw->dCBWTag = tag++;
165 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
173static void
174get_csw (endpoint_t *ep, csw_t *csw)
175{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000176 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1))
177 clear_stall (ep);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000178}
179
180static int
181execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
182 u8 *buf, int buflen)
183{
184 cbw_t cbw;
185 csw_t csw;
186
187 int always_succeed = 0;
188 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
189 always_succeed = 1;
190 }
191 wrap_cbw (&cbw, buflen, dir, cb, cblen);
192 if (dev->controller->
193 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000194 reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000195 return 1;
196 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000197 if (buflen > 0) {
198 if (dir == cbw_direction_data_in) {
199 if (dev->controller->
200 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
201 clear_stall (MSC_INST (dev)->bulk_in);
202 return 1;
203 }
204 } else {
205 if (dev->controller->
206 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
207 clear_stall (MSC_INST (dev)->bulk_out);
208 return 1;
209 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000210 }
211 }
212 get_csw (MSC_INST (dev)->bulk_in, &csw);
213 if (always_succeed == 1) {
214 // return success, regardless of message
215 return 0;
216 }
217 if (csw.bCSWStatus == 2) {
218 // phase error, reset transport
219 reset_transport (dev);
220 return 1;
221 }
222 if (csw.bCSWStatus == 0) {
223 // no error, exit
224 return 0;
225 }
226 // error "check condition" or reserved error
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000227 request_sense (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000228 return 1;
229}
230
231typedef struct {
232 unsigned char command; //0
233 unsigned char res1; //1
234 unsigned int block; //2-5
235 unsigned char res2; //6
236 unsigned short numblocks; //7-8
237 unsigned char res3; //9 - the block is 10 bytes long
238} __attribute__ ((packed)) cmdblock_t;
239
240typedef struct {
241 unsigned char command; //0
242 unsigned char res1; //1
243 unsigned char res2; //2
244 unsigned char res3; //3
245 unsigned char lun; //4
246 unsigned char res4; //5
247} __attribute__ ((packed)) cmdblock6_t;
248
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000249/**
250 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
251 * start and count from 512b units.
252 * Start and count must be aligned so that they match the native
253 * sector size.
254 *
255 * @param dev device to access
256 * @param start first sector to access
257 * @param n number of sectors to access
258 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
259 * @param buf buffer to read into or write from. Must be at least n*512 bytes
260 * @return 0 on success, 1 on failure
261 */
262int
263readwrite_blocks_512 (usbdev_t *dev, int start, int n,
264 cbw_direction dir, u8 *buf)
265{
266 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
267 return readwrite_blocks (dev, start / blocksize_divider,
268 n / blocksize_divider, dir, buf);
269}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000270
271/**
272 * Reads or writes a number of sequential blocks on a USB storage device.
273 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
274 * of at most 2TB. It assumes sectors of 512 bytes.
275 *
276 * @param dev device to access
277 * @param start first sector to access
278 * @param n number of sectors to access
279 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000280 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000281 * @return 0 on success, 1 on failure
282 */
283int
284readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
285{
286 cmdblock_t cb;
287 memset (&cb, 0, sizeof (cb));
288 if (dir == cbw_direction_data_in) {
289 // read
290 cb.command = 0x28;
291 } else {
292 // write
293 cb.command = 0x2a;
294 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000295 cb.block = htonl (start);
296 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000297
Patrick Georgid21f68b2008-09-02 16:06:22 +0000298 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000299 n * MSC_INST(dev)->blocksize);
300}
301
302/* Only request it, we don't interpret it.
303 On certain errors, that's necessary to get devices out of
304 a special state called "Contingent Allegiance Condition" */
305static int
306request_sense (usbdev_t *dev)
307{
308 u8 buf[19];
309 cmdblock6_t cb;
310 memset (&cb, 0, sizeof (cb));
311 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000312
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000313 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
314 sizeof (cb), buf, 19);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000315}
316
317static int
318test_unit_ready (usbdev_t *dev)
319{
320 cmdblock6_t cb;
321 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
322 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
323 sizeof (cb), 0, 0);
324}
325
326static int
327spin_up (usbdev_t *dev)
328{
329 cmdblock6_t cb;
330 memset (&cb, 0, sizeof (cb));
331 cb.command = 0x1b;
332 cb.lun = 1;
333 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
334 sizeof (cb), 0, 0);
335}
336
337static void
338read_capacity (usbdev_t *dev)
339{
340 cmdblock_t cb;
341 memset (&cb, 0, sizeof (cb));
342 cb.command = 0x25; // read capacity
343 u8 buf[8];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000344
Mathias Krausec4716b42011-06-08 15:36:55 +0200345 debug ("Reading capacity of mass storage device.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000346 int count = 0;
347 while ((count++ < 20)
348 &&
349 (execute_command
350 (dev, cbw_direction_data_in, (u8 *) &cb, sizeof (cb), buf,
351 8) == 1));
352 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000353 // 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 +0200354 printf (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000355 MSC_INST (dev)->numblocks = 0xffffffff;
356 MSC_INST (dev)->blocksize = 512;
357 } else {
358 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
359 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
360 }
Mathias Krausec4716b42011-06-08 15:36:55 +0200361 printf (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
362 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200363 /* round down high block counts to avoid integer overflow */
364 MSC_INST (dev)->numblocks > 1000000
365 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200366 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000367}
368
369void
370usb_msc_init (usbdev_t *dev)
371{
372 int i, timeout;
373
374 dev->destroy = usb_msc_destroy;
375 dev->poll = usb_msc_poll;
376
377 configuration_descriptor_t *cd =
378 (configuration_descriptor_t *) dev->configuration;
379 interface_descriptor_t *interface =
380 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
381
Mathias Krausec4716b42011-06-08 15:36:55 +0200382 debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000383 msc_subclass_strings[interface->bInterfaceSubClass]);
Mathias Krausec4716b42011-06-08 15:36:55 +0200384 debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000385 msc_protocol_strings[interface->bInterfaceProtocol]);
386
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000387
388 if (interface->bInterfaceProtocol != 0x50) {
389 printf (" Protocol not supported.\n");
390 return;
391 }
392
393 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
394 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
395 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000396 /* 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 +0000397 printf (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000398 return;
399 }
400
401 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000402 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100403 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000404
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000405 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000406 MSC_INST (dev)->bulk_in = 0;
407 MSC_INST (dev)->bulk_out = 0;
408
409 for (i = 1; i <= dev->num_endp; i++) {
410 if (dev->endpoints[i].endpoint == 0)
411 continue;
412 if (dev->endpoints[i].type != BULK)
413 continue;
414 if ((dev->endpoints[i].direction == IN)
415 && (MSC_INST (dev)->bulk_in == 0))
416 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
417 if ((dev->endpoints[i].direction == OUT)
418 && (MSC_INST (dev)->bulk_out == 0))
419 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
420 }
421
422 if (MSC_INST (dev)->bulk_in == 0)
423 fatal ("couldn't find bulk-in endpoint");
424 if (MSC_INST (dev)->bulk_out == 0)
425 fatal ("couldn't find bulk-out endpoint");
Mathias Krausec4716b42011-06-08 15:36:55 +0200426 debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000427 MSC_INST (dev)->bulk_in->endpoint,
428 MSC_INST (dev)->bulk_out->endpoint);
429
Mathias Krausec4716b42011-06-08 15:36:55 +0200430 debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000431
Mathias Krausec4716b42011-06-08 15:36:55 +0200432 printf (" Waiting for device to become ready...");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000433 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000434 while (test_unit_ready (dev) && --timeout) {
435 mdelay (100);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000436 if (!(timeout % 10))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000437 printf (".");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000438 }
439 if (test_unit_ready (dev)) {
440 printf ("timeout. Device not ready. Still trying...\n");
441 } else {
442 printf ("ok.\n");
443 }
444
Mathias Krausec4716b42011-06-08 15:36:55 +0200445 debug (" spin up");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000446 for (i = 0; i < 30; i++) {
Mathias Krausec4716b42011-06-08 15:36:55 +0200447 debug (".");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000448 if (!spin_up (dev)) {
Mathias Krausec4716b42011-06-08 15:36:55 +0200449 debug (" OK.");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000450 break;
451 }
452 mdelay (100);
453 }
Mathias Krausec4716b42011-06-08 15:36:55 +0200454 debug ("\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000455
456 read_capacity (dev);
Patrick Georgi4727c072008-10-16 19:20:51 +0000457 if (usbdisk_create)
458 usbdisk_create (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000459}