blob: 5af3330b2f3f6c7087e1082a57c2e0691f6def43 [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 }
197 mdelay (10);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000198 if (buflen > 0) {
199 if (dir == cbw_direction_data_in) {
200 if (dev->controller->
201 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
202 clear_stall (MSC_INST (dev)->bulk_in);
203 return 1;
204 }
205 } else {
206 if (dev->controller->
207 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
208 clear_stall (MSC_INST (dev)->bulk_out);
209 return 1;
210 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000211 }
212 }
213 get_csw (MSC_INST (dev)->bulk_in, &csw);
214 if (always_succeed == 1) {
215 // return success, regardless of message
216 return 0;
217 }
218 if (csw.bCSWStatus == 2) {
219 // phase error, reset transport
220 reset_transport (dev);
221 return 1;
222 }
223 if (csw.bCSWStatus == 0) {
224 // no error, exit
225 return 0;
226 }
227 // error "check condition" or reserved error
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000228 request_sense (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000229 return 1;
230}
231
232typedef struct {
233 unsigned char command; //0
234 unsigned char res1; //1
235 unsigned int block; //2-5
236 unsigned char res2; //6
237 unsigned short numblocks; //7-8
238 unsigned char res3; //9 - the block is 10 bytes long
239} __attribute__ ((packed)) cmdblock_t;
240
241typedef struct {
242 unsigned char command; //0
243 unsigned char res1; //1
244 unsigned char res2; //2
245 unsigned char res3; //3
246 unsigned char lun; //4
247 unsigned char res4; //5
248} __attribute__ ((packed)) cmdblock6_t;
249
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000250/**
251 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
252 * start and count from 512b units.
253 * Start and count must be aligned so that they match the native
254 * sector size.
255 *
256 * @param dev device to access
257 * @param start first sector to access
258 * @param n number of sectors to access
259 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
260 * @param buf buffer to read into or write from. Must be at least n*512 bytes
261 * @return 0 on success, 1 on failure
262 */
263int
264readwrite_blocks_512 (usbdev_t *dev, int start, int n,
265 cbw_direction dir, u8 *buf)
266{
267 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
268 return readwrite_blocks (dev, start / blocksize_divider,
269 n / blocksize_divider, dir, buf);
270}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000271
272/**
273 * Reads or writes a number of sequential blocks on a USB storage device.
274 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
275 * of at most 2TB. It assumes sectors of 512 bytes.
276 *
277 * @param dev device to access
278 * @param start first sector to access
279 * @param n number of sectors to access
280 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000281 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000282 * @return 0 on success, 1 on failure
283 */
284int
285readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
286{
287 cmdblock_t cb;
288 memset (&cb, 0, sizeof (cb));
289 if (dir == cbw_direction_data_in) {
290 // read
291 cb.command = 0x28;
292 } else {
293 // write
294 cb.command = 0x2a;
295 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000296 cb.block = htonl (start);
297 cb.numblocks = htonw (n);
298
Patrick Georgid21f68b2008-09-02 16:06:22 +0000299 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000300 n * MSC_INST(dev)->blocksize);
301}
302
303/* Only request it, we don't interpret it.
304 On certain errors, that's necessary to get devices out of
305 a special state called "Contingent Allegiance Condition" */
306static int
307request_sense (usbdev_t *dev)
308{
309 u8 buf[19];
310 cmdblock6_t cb;
311 memset (&cb, 0, sizeof (cb));
312 cb.command = 0x3;
313
314 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
315 sizeof (cb), buf, 19);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000316}
317
318static int
319test_unit_ready (usbdev_t *dev)
320{
321 cmdblock6_t cb;
322 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
323 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
324 sizeof (cb), 0, 0);
325}
326
327static int
328spin_up (usbdev_t *dev)
329{
330 cmdblock6_t cb;
331 memset (&cb, 0, sizeof (cb));
332 cb.command = 0x1b;
333 cb.lun = 1;
334 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
335 sizeof (cb), 0, 0);
336}
337
338static void
339read_capacity (usbdev_t *dev)
340{
341 cmdblock_t cb;
342 memset (&cb, 0, sizeof (cb));
343 cb.command = 0x25; // read capacity
344 u8 buf[8];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000345
346 printf ("Reading capacity of mass storage device.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000347 int count = 0;
348 while ((count++ < 20)
349 &&
350 (execute_command
351 (dev, cbw_direction_data_in, (u8 *) &cb, sizeof (cb), buf,
352 8) == 1));
353 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000354 // still not successful, assume 2tb in 512byte sectors, which is just the same garbage as any other number, but probably more usable.
355 printf ("Assuming 2TB in 512byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000356 MSC_INST (dev)->numblocks = 0xffffffff;
357 MSC_INST (dev)->blocksize = 512;
358 } else {
359 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
360 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
361 }
362 printf (" has %d blocks sized %db\n", MSC_INST (dev)->numblocks,
363 MSC_INST (dev)->blocksize);
364}
365
366void
367usb_msc_init (usbdev_t *dev)
368{
369 int i, timeout;
370
371 dev->destroy = usb_msc_destroy;
372 dev->poll = usb_msc_poll;
373
374 configuration_descriptor_t *cd =
375 (configuration_descriptor_t *) dev->configuration;
376 interface_descriptor_t *interface =
377 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
378
379 printf (" it uses %s command set\n",
380 msc_subclass_strings[interface->bInterfaceSubClass]);
381 printf (" it uses %s protocol\n",
382 msc_protocol_strings[interface->bInterfaceProtocol]);
383
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000384
385 if (interface->bInterfaceProtocol != 0x50) {
386 printf (" Protocol not supported.\n");
387 return;
388 }
389
390 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
391 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
392 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000393 /* 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 +0000394 printf (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000395 return;
396 }
397
398 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000399 if (!dev->data)
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000400 usb_fatal ("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000401
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000402 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000403 MSC_INST (dev)->bulk_in = 0;
404 MSC_INST (dev)->bulk_out = 0;
405
406 for (i = 1; i <= dev->num_endp; i++) {
407 if (dev->endpoints[i].endpoint == 0)
408 continue;
409 if (dev->endpoints[i].type != BULK)
410 continue;
411 if ((dev->endpoints[i].direction == IN)
412 && (MSC_INST (dev)->bulk_in == 0))
413 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
414 if ((dev->endpoints[i].direction == OUT)
415 && (MSC_INST (dev)->bulk_out == 0))
416 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
417 }
418
419 if (MSC_INST (dev)->bulk_in == 0)
420 fatal ("couldn't find bulk-in endpoint");
421 if (MSC_INST (dev)->bulk_out == 0)
422 fatal ("couldn't find bulk-out endpoint");
423 printf (" using endpoint %x as in, %x as out\n",
424 MSC_INST (dev)->bulk_in->endpoint,
425 MSC_INST (dev)->bulk_out->endpoint);
426
427 printf (" has %d luns\n", get_max_luns (dev) + 1);
428
429 printf (" Waiting for device to become ready... ");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000430 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000431 while (test_unit_ready (dev) && --timeout) {
432 mdelay (100);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000433 if (!(timeout % 10))
434 printf (".");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000435 }
436 if (test_unit_ready (dev)) {
437 printf ("timeout. Device not ready. Still trying...\n");
438 } else {
439 printf ("ok.\n");
440 }
441
442 printf (" spin up");
443 for (i = 0; i < 30; i++) {
444 printf (".");
445 if (!spin_up (dev)) {
446 printf (" OK.");
447 break;
448 }
449 mdelay (100);
450 }
451 printf ("\n");
452
453 read_capacity (dev);
Patrick Georgi4727c072008-10-16 19:20:51 +0000454 if (usbdisk_create)
455 usbdisk_create (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000456}