blob: 0032f581bbc2b8f96cd26e35fa96063bd70be42b [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
Gabe Black0af03d22012-03-19 03:06:46 -070030#include <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)) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700146 usb_debug ("Detaching unresponsive device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200147 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->
Nico Huberef88e102012-11-21 16:25:55 +0100230 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000231 clear_stall (MSC_INST (dev)->bulk_in);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000232 } else {
233 if (dev->controller->
Nico Huberef88e102012-11-21 16:25:55 +0100234 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000235 clear_stall (MSC_INST (dev)->bulk_out);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000236 }
237 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200238 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
239 if (ret) {
240 return ret;
241 } else if (always_succeed == 1) {
242 /* return success, regardless of message */
243 return MSC_COMMAND_OK;
244 } else if (csw.bCSWStatus == 2) {
245 /* phase error, reset transport */
246 return reset_transport (dev);
247 } else if (csw.bCSWStatus == 0) {
248 if ((csw.dCSWDataResidue == 0) || residue_ok)
249 /* no error, exit */
250 return MSC_COMMAND_OK;
251 else
252 /* missed some bytes */
253 return MSC_COMMAND_FAIL;
254 } else {
255 if (cb[0] == 0x03)
256 /* requesting sense failed, that's bad */
257 return MSC_COMMAND_FAIL;
258 /* error "check condition" or reserved error */
259 ret = request_sense (dev);
260 /* return fail or the status of request_sense if it's worse */
261 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000262 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000263}
264
265typedef struct {
266 unsigned char command; //0
267 unsigned char res1; //1
268 unsigned int block; //2-5
269 unsigned char res2; //6
270 unsigned short numblocks; //7-8
271 unsigned char res3; //9 - the block is 10 bytes long
272} __attribute__ ((packed)) cmdblock_t;
273
274typedef struct {
275 unsigned char command; //0
276 unsigned char res1; //1
277 unsigned char res2; //2
278 unsigned char res3; //3
279 unsigned char lun; //4
280 unsigned char res4; //5
281} __attribute__ ((packed)) cmdblock6_t;
282
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000283/**
284 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
285 * start and count from 512b units.
286 * Start and count must be aligned so that they match the native
287 * sector size.
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
293 * @param buf buffer to read into or write from. Must be at least n*512 bytes
294 * @return 0 on success, 1 on failure
295 */
296int
297readwrite_blocks_512 (usbdev_t *dev, int start, int n,
298 cbw_direction dir, u8 *buf)
299{
300 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
301 return readwrite_blocks (dev, start / blocksize_divider,
302 n / blocksize_divider, dir, buf);
303}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000304
305/**
306 * Reads or writes a number of sequential blocks on a USB storage device.
307 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
308 * of at most 2TB. It assumes sectors of 512 bytes.
309 *
310 * @param dev device to access
311 * @param start first sector to access
312 * @param n number of sectors to access
313 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000314 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000315 * @return 0 on success, 1 on failure
316 */
317int
318readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
319{
320 cmdblock_t cb;
321 memset (&cb, 0, sizeof (cb));
322 if (dir == cbw_direction_data_in) {
323 // read
324 cb.command = 0x28;
325 } else {
326 // write
327 cb.command = 0x2a;
328 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000329 cb.block = htonl (start);
330 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000331
Patrick Georgid21f68b2008-09-02 16:06:22 +0000332 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200333 n * MSC_INST(dev)->blocksize, 0)
334 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000335}
336
337/* Only request it, we don't interpret it.
338 On certain errors, that's necessary to get devices out of
339 a special state called "Contingent Allegiance Condition" */
340static int
341request_sense (usbdev_t *dev)
342{
343 u8 buf[19];
344 cmdblock6_t cb;
345 memset (&cb, 0, sizeof (cb));
346 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000347
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000348 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200349 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000350}
351
352static int
353test_unit_ready (usbdev_t *dev)
354{
355 cmdblock6_t cb;
356 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
357 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200358 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000359}
360
361static int
362spin_up (usbdev_t *dev)
363{
364 cmdblock6_t cb;
365 memset (&cb, 0, sizeof (cb));
366 cb.command = 0x1b;
367 cb.lun = 1;
368 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200369 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000370}
371
Nico Huber79e1f2f2012-06-01 09:50:11 +0200372static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000373read_capacity (usbdev_t *dev)
374{
375 cmdblock_t cb;
376 memset (&cb, 0, sizeof (cb));
377 cb.command = 0x25; // read capacity
378 u8 buf[8];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000379
Gabe Black93ded592012-11-01 15:44:10 -0700380 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200381 int count = 0, ret;
382 while (count++ < 20) {
383 switch (ret = execute_command
384 (dev, cbw_direction_data_in, (u8 *) &cb,
385 sizeof (cb), buf, 8, 0)) {
386 case MSC_COMMAND_OK:
387 break;
388 case MSC_COMMAND_FAIL:
389 continue;
390 default: /* if it's worse return */
391 return ret;
392 }
393 break;
394 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000395 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000396 // still not successful, assume 2tb in 512byte sectors, which is just the same garbage as any other number, but probably more usable.
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700397 usb_debug (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000398 MSC_INST (dev)->numblocks = 0xffffffff;
399 MSC_INST (dev)->blocksize = 512;
400 } else {
401 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
402 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
403 }
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700404 usb_debug (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
Mathias Krausec4716b42011-06-08 15:36:55 +0200405 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200406 /* round down high block counts to avoid integer overflow */
407 MSC_INST (dev)->numblocks > 1000000
408 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200409 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200410 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000411}
412
413void
414usb_msc_init (usbdev_t *dev)
415{
416 int i, timeout;
417
Nico Huber445a3a02012-06-21 10:52:49 +0200418 /* init .data before setting .destroy */
419 dev->data = NULL;
420
Patrick Georgid21f68b2008-09-02 16:06:22 +0000421 dev->destroy = usb_msc_destroy;
422 dev->poll = usb_msc_poll;
423
424 configuration_descriptor_t *cd =
425 (configuration_descriptor_t *) dev->configuration;
426 interface_descriptor_t *interface =
427 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
428
Gabe Black93ded592012-11-01 15:44:10 -0700429 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000430 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700431 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000432 msc_protocol_strings[interface->bInterfaceProtocol]);
433
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000434
435 if (interface->bInterfaceProtocol != 0x50) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700436 usb_debug (" Protocol not supported.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000437 return;
438 }
439
440 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
441 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
442 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000443 /* Other protocols, such as ATAPI don't seem to be very popular. looks like ATAPI would be really easy to add, if necessary. */
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700444 usb_debug (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000445 return;
446 }
447
448 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000449 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100450 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000451
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000452 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000453 MSC_INST (dev)->bulk_in = 0;
454 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200455 MSC_INST (dev)->usbdisk_created = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000456
457 for (i = 1; i <= dev->num_endp; i++) {
458 if (dev->endpoints[i].endpoint == 0)
459 continue;
460 if (dev->endpoints[i].type != BULK)
461 continue;
462 if ((dev->endpoints[i].direction == IN)
463 && (MSC_INST (dev)->bulk_in == 0))
464 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
465 if ((dev->endpoints[i].direction == OUT)
466 && (MSC_INST (dev)->bulk_out == 0))
467 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
468 }
469
Nico Huber445a3a02012-06-21 10:52:49 +0200470 if (MSC_INST (dev)->bulk_in == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700471 usb_debug("couldn't find bulk-in endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200472 return;
473 }
474 if (MSC_INST (dev)->bulk_out == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700475 usb_debug("couldn't find bulk-out endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200476 return;
477 }
Gabe Black93ded592012-11-01 15:44:10 -0700478 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000479 MSC_INST (dev)->bulk_in->endpoint,
480 MSC_INST (dev)->bulk_out->endpoint);
481
Gabe Black93ded592012-11-01 15:44:10 -0700482 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000483
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700484 usb_debug (" Waiting for device to become ready...");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000485 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Nico Huber79e1f2f2012-06-01 09:50:11 +0200486 while (timeout--) {
487 switch (test_unit_ready (dev)) {
488 case MSC_COMMAND_OK:
489 break;
490 case MSC_COMMAND_FAIL:
491 mdelay (100);
492 if (!(timeout % 10))
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700493 usb_debug (".");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200494 continue;
495 default: /* if it's worse return */
496 return;
497 }
498 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000499 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200500 if (timeout < 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700501 usb_debug ("timeout. Device not ready. Still trying...\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000502 } else {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700503 usb_debug ("ok.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000504 }
505
Gabe Black93ded592012-11-01 15:44:10 -0700506 usb_debug (" spin up");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000507 for (i = 0; i < 30; i++) {
Gabe Black93ded592012-11-01 15:44:10 -0700508 usb_debug (".");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200509 switch (spin_up (dev)) {
510 case MSC_COMMAND_OK:
Gabe Black93ded592012-11-01 15:44:10 -0700511 usb_debug (" OK.");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000512 break;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200513 case MSC_COMMAND_FAIL:
514 mdelay (100);
515 continue;
516 default: /* if it's worse return */
517 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000518 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200519 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000520 }
Gabe Black93ded592012-11-01 15:44:10 -0700521 usb_debug ("\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000522
Nico Huber445a3a02012-06-21 10:52:49 +0200523 if ((read_capacity (dev) == MSC_COMMAND_OK) && usbdisk_create) {
Patrick Georgi4727c072008-10-16 19:20:51 +0000524 usbdisk_create (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200525 MSC_INST (dev)->usbdisk_created = 1;
526 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000527}