blob: db369f7bd1c9c29b3c3a2c1fea4fe31ee7a4de3d [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{
Nico Huber445a3a02012-06-21 10:52:49 +020073 if (dev->data) {
74 if (MSC_INST (dev)->usbdisk_created && usbdisk_remove)
75 usbdisk_remove (dev);
76 free (dev->data);
77 }
Patrick Georgid21f68b2008-09-02 16:06:22 +000078 dev->data = 0;
79}
80
81static void
82usb_msc_poll (usbdev_t *dev)
83{
84}
85
86const int DEV_RESET = 0xff;
87const int GET_MAX_LUN = 0xfe;
88
89const unsigned int cbw_signature = 0x43425355;
90const unsigned int csw_signature = 0x53425355;
91
92typedef struct {
93 unsigned int dCBWSignature;
94 unsigned int dCBWTag;
95 unsigned int dCBWDataTransferLength;
96 unsigned char bmCBWFlags;
97 unsigned long bCBWLUN:4;
98 unsigned long:4;
99 unsigned long bCBWCBLength:5;
100 unsigned long:3;
101 unsigned char CBWCB[31 - 15];
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000102} __attribute__ ((packed)) cbw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000103
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000104typedef struct {
105 unsigned int dCSWSignature;
106 unsigned int dCSWTag;
107 unsigned int dCSWDataResidue;
108 unsigned char bCSWStatus;
109} __attribute__ ((packed)) csw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000110
Nico Huber79e1f2f2012-06-01 09:50:11 +0200111enum {
112 /*
113 * MSC commands can be
114 * successful,
115 * fail with proper response or
116 * fail totally, which results in detaching of the usb device.
117 * In the latter case the caller has to make sure, that he won't
118 * use the device any more.
119 */
120 MSC_COMMAND_OK = 0, MSC_COMMAND_FAIL, MSC_COMMAND_DETACHED
121};
122
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000123static int
124request_sense (usbdev_t *dev);
125
Nico Huber79e1f2f2012-06-01 09:50:11 +0200126static int
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000127reset_transport (usbdev_t *dev)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000128{
129 dev_req_t dr;
130 memset (&dr, 0, sizeof (dr));
131 dr.bmRequestType = 0;
132 dr.data_dir = host_to_device;
133#ifndef QEMU
134 dr.req_type = class_type;
135 dr.req_recp = iface_recp;
136#endif
137 dr.bRequest = DEV_RESET;
138 dr.wValue = 0;
139 dr.wIndex = 0;
140 dr.wLength = 0;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200141
142 /* if any of these fails, detach device, as we are lost */
143 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) ||
144 clear_stall (MSC_INST (dev)->bulk_in) ||
145 clear_stall (MSC_INST (dev)->bulk_out)) {
146 printf ("Detaching unresponsive device.\n");
147 usb_detach_device (dev->controller, dev->address);
148 return MSC_COMMAND_DETACHED;
149 }
150 /* return fail as we are only called in case of failure */
151 return MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000152}
153
154/* device may stall this command, so beware! */
155static int
156get_max_luns (usbdev_t *dev)
157{
158 unsigned char luns = 75;
159 dev_req_t dr;
160 dr.bmRequestType = 0;
161 dr.data_dir = device_to_host;
162#ifndef QEMU
163 dr.req_type = class_type;
164 dr.req_recp = iface_recp;
165#endif
166 dr.bRequest = GET_MAX_LUN;
167 dr.wValue = 0;
168 dr.wIndex = 0;
169 dr.wLength = 1;
170 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
171 luns = 0; // assume only 1 lun if req fails
172 }
173 return luns;
174}
175
Nico Huber43b9f322012-05-21 14:05:41 +0200176unsigned int tag;
177unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000178
179static void
180wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
181 int cmdlen)
182{
183 memset (cbw, 0, sizeof (cbw_t));
184
185 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200186 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000187 cbw->bCBWLUN = lun; // static value per device
188
189 cbw->dCBWDataTransferLength = datalen;
190 cbw->bmCBWFlags = dir;
191 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
192 cbw->bCBWCBLength = cmdlen;
193}
194
Nico Huber43b9f322012-05-21 14:05:41 +0200195static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000196get_csw (endpoint_t *ep, csw_t *csw)
197{
Nico Huber43b9f322012-05-21 14:05:41 +0200198 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000199 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200200 if (ep->dev->controller->bulk
201 (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200202 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200203 }
204 }
205 if (csw->dCSWTag != tag) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200206 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200207 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200208 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000209}
210
211static int
212execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200213 u8 *buf, int buflen, int residue_ok)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000214{
215 cbw_t cbw;
216 csw_t csw;
217
218 int always_succeed = 0;
219 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
220 always_succeed = 1;
221 }
222 wrap_cbw (&cbw, buflen, dir, cb, cblen);
223 if (dev->controller->
224 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200225 return reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000226 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000227 if (buflen > 0) {
228 if (dir == cbw_direction_data_in) {
229 if (dev->controller->
230 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
231 clear_stall (MSC_INST (dev)->bulk_in);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200232 return MSC_COMMAND_FAIL;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000233 }
234 } else {
235 if (dev->controller->
236 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
237 clear_stall (MSC_INST (dev)->bulk_out);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200238 return MSC_COMMAND_FAIL;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000239 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000240 }
241 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200242 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
243 if (ret) {
244 return ret;
245 } else if (always_succeed == 1) {
246 /* return success, regardless of message */
247 return MSC_COMMAND_OK;
248 } else if (csw.bCSWStatus == 2) {
249 /* phase error, reset transport */
250 return reset_transport (dev);
251 } else if (csw.bCSWStatus == 0) {
252 if ((csw.dCSWDataResidue == 0) || residue_ok)
253 /* no error, exit */
254 return MSC_COMMAND_OK;
255 else
256 /* missed some bytes */
257 return MSC_COMMAND_FAIL;
258 } else {
259 if (cb[0] == 0x03)
260 /* requesting sense failed, that's bad */
261 return MSC_COMMAND_FAIL;
262 /* error "check condition" or reserved error */
263 ret = request_sense (dev);
264 /* return fail or the status of request_sense if it's worse */
265 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000266 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000267}
268
269typedef struct {
270 unsigned char command; //0
271 unsigned char res1; //1
272 unsigned int block; //2-5
273 unsigned char res2; //6
274 unsigned short numblocks; //7-8
275 unsigned char res3; //9 - the block is 10 bytes long
276} __attribute__ ((packed)) cmdblock_t;
277
278typedef struct {
279 unsigned char command; //0
280 unsigned char res1; //1
281 unsigned char res2; //2
282 unsigned char res3; //3
283 unsigned char lun; //4
284 unsigned char res4; //5
285} __attribute__ ((packed)) cmdblock6_t;
286
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000287/**
288 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
289 * start and count from 512b units.
290 * Start and count must be aligned so that they match the native
291 * sector size.
292 *
293 * @param dev device to access
294 * @param start first sector to access
295 * @param n number of sectors to access
296 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
297 * @param buf buffer to read into or write from. Must be at least n*512 bytes
298 * @return 0 on success, 1 on failure
299 */
300int
301readwrite_blocks_512 (usbdev_t *dev, int start, int n,
302 cbw_direction dir, u8 *buf)
303{
304 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
305 return readwrite_blocks (dev, start / blocksize_divider,
306 n / blocksize_divider, dir, buf);
307}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000308
309/**
310 * Reads or writes a number of sequential blocks on a USB storage device.
311 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
312 * of at most 2TB. It assumes sectors of 512 bytes.
313 *
314 * @param dev device to access
315 * @param start first sector to access
316 * @param n number of sectors to access
317 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000318 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000319 * @return 0 on success, 1 on failure
320 */
321int
322readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
323{
324 cmdblock_t cb;
325 memset (&cb, 0, sizeof (cb));
326 if (dir == cbw_direction_data_in) {
327 // read
328 cb.command = 0x28;
329 } else {
330 // write
331 cb.command = 0x2a;
332 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000333 cb.block = htonl (start);
334 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000335
Patrick Georgid21f68b2008-09-02 16:06:22 +0000336 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200337 n * MSC_INST(dev)->blocksize, 0)
338 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000339}
340
341/* Only request it, we don't interpret it.
342 On certain errors, that's necessary to get devices out of
343 a special state called "Contingent Allegiance Condition" */
344static int
345request_sense (usbdev_t *dev)
346{
347 u8 buf[19];
348 cmdblock6_t cb;
349 memset (&cb, 0, sizeof (cb));
350 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000351
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000352 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200353 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000354}
355
356static int
357test_unit_ready (usbdev_t *dev)
358{
359 cmdblock6_t cb;
360 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
361 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200362 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000363}
364
365static int
366spin_up (usbdev_t *dev)
367{
368 cmdblock6_t cb;
369 memset (&cb, 0, sizeof (cb));
370 cb.command = 0x1b;
371 cb.lun = 1;
372 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200373 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000374}
375
Nico Huber79e1f2f2012-06-01 09:50:11 +0200376static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000377read_capacity (usbdev_t *dev)
378{
379 cmdblock_t cb;
380 memset (&cb, 0, sizeof (cb));
381 cb.command = 0x25; // read capacity
382 u8 buf[8];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000383
Gabe Black93ded592012-11-01 15:44:10 -0700384 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200385 int count = 0, ret;
386 while (count++ < 20) {
387 switch (ret = execute_command
388 (dev, cbw_direction_data_in, (u8 *) &cb,
389 sizeof (cb), buf, 8, 0)) {
390 case MSC_COMMAND_OK:
391 break;
392 case MSC_COMMAND_FAIL:
393 continue;
394 default: /* if it's worse return */
395 return ret;
396 }
397 break;
398 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000399 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000400 // 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 +0200401 printf (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000402 MSC_INST (dev)->numblocks = 0xffffffff;
403 MSC_INST (dev)->blocksize = 512;
404 } else {
405 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
406 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
407 }
Mathias Krausec4716b42011-06-08 15:36:55 +0200408 printf (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
409 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200410 /* round down high block counts to avoid integer overflow */
411 MSC_INST (dev)->numblocks > 1000000
412 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200413 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200414 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000415}
416
417void
418usb_msc_init (usbdev_t *dev)
419{
420 int i, timeout;
421
Nico Huber445a3a02012-06-21 10:52:49 +0200422 /* init .data before setting .destroy */
423 dev->data = NULL;
424
Patrick Georgid21f68b2008-09-02 16:06:22 +0000425 dev->destroy = usb_msc_destroy;
426 dev->poll = usb_msc_poll;
427
428 configuration_descriptor_t *cd =
429 (configuration_descriptor_t *) dev->configuration;
430 interface_descriptor_t *interface =
431 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
432
Gabe Black93ded592012-11-01 15:44:10 -0700433 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000434 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700435 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000436 msc_protocol_strings[interface->bInterfaceProtocol]);
437
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000438
439 if (interface->bInterfaceProtocol != 0x50) {
440 printf (" Protocol not supported.\n");
441 return;
442 }
443
444 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
445 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
446 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000447 /* 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 +0000448 printf (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000449 return;
450 }
451
452 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000453 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100454 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000455
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000456 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000457 MSC_INST (dev)->bulk_in = 0;
458 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200459 MSC_INST (dev)->usbdisk_created = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000460
461 for (i = 1; i <= dev->num_endp; i++) {
462 if (dev->endpoints[i].endpoint == 0)
463 continue;
464 if (dev->endpoints[i].type != BULK)
465 continue;
466 if ((dev->endpoints[i].direction == IN)
467 && (MSC_INST (dev)->bulk_in == 0))
468 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
469 if ((dev->endpoints[i].direction == OUT)
470 && (MSC_INST (dev)->bulk_out == 0))
471 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
472 }
473
Nico Huber445a3a02012-06-21 10:52:49 +0200474 if (MSC_INST (dev)->bulk_in == 0) {
475 printf("couldn't find bulk-in endpoint");
476 return;
477 }
478 if (MSC_INST (dev)->bulk_out == 0) {
479 printf("couldn't find bulk-out endpoint");
480 return;
481 }
Gabe Black93ded592012-11-01 15:44:10 -0700482 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000483 MSC_INST (dev)->bulk_in->endpoint,
484 MSC_INST (dev)->bulk_out->endpoint);
485
Gabe Black93ded592012-11-01 15:44:10 -0700486 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000487
Mathias Krausec4716b42011-06-08 15:36:55 +0200488 printf (" Waiting for device to become ready...");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000489 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Nico Huber79e1f2f2012-06-01 09:50:11 +0200490 while (timeout--) {
491 switch (test_unit_ready (dev)) {
492 case MSC_COMMAND_OK:
493 break;
494 case MSC_COMMAND_FAIL:
495 mdelay (100);
496 if (!(timeout % 10))
497 printf (".");
498 continue;
499 default: /* if it's worse return */
500 return;
501 }
502 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000503 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200504 if (timeout < 0) {
Patrick Georgid21f68b2008-09-02 16:06:22 +0000505 printf ("timeout. Device not ready. Still trying...\n");
506 } else {
507 printf ("ok.\n");
508 }
509
Gabe Black93ded592012-11-01 15:44:10 -0700510 usb_debug (" spin up");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000511 for (i = 0; i < 30; i++) {
Gabe Black93ded592012-11-01 15:44:10 -0700512 usb_debug (".");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200513 switch (spin_up (dev)) {
514 case MSC_COMMAND_OK:
Gabe Black93ded592012-11-01 15:44:10 -0700515 usb_debug (" OK.");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000516 break;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200517 case MSC_COMMAND_FAIL:
518 mdelay (100);
519 continue;
520 default: /* if it's worse return */
521 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000522 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200523 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000524 }
Gabe Black93ded592012-11-01 15:44:10 -0700525 usb_debug ("\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000526
Nico Huber445a3a02012-06-21 10:52:49 +0200527 if ((read_capacity (dev) == MSC_COMMAND_OK) && usbdisk_create) {
Patrick Georgi4727c072008-10-16 19:20:51 +0000528 usbdisk_create (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200529 MSC_INST (dev)->usbdisk_created = 1;
530 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000531}