blob: ad7e82f3b07d52760559e4066d17251f2569a51b [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
Stefan Reinauer8992e532013-05-02 16:16:41 -070030//#define USB_DEBUG
Gabe Black0af03d22012-03-19 03:06:46 -070031#include <endian.h>
Jordan Crouse29061a52008-09-11 17:29:00 +000032#include <usb/usb.h>
33#include <usb/usbmsc.h>
34#include <usb/usbdisk.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000035
36enum {
37 msc_subclass_rbc = 0x1,
38 msc_subclass_mmc2 = 0x2,
39 msc_subclass_qic157 = 0x3,
40 msc_subclass_ufi = 0x4,
41 msc_subclass_sff8070i = 0x5,
42 msc_subclass_scsitrans = 0x6
43};
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000044
Patrick Georgid21f68b2008-09-02 16:06:22 +000045static const char *msc_subclass_strings[7] = {
46 "(none)",
47 "RBC",
48 "MMC-2",
49 "QIC-157",
50 "UFI",
51 "SFF-8070i",
52 "SCSI transparent"
53};
54enum {
55 msc_proto_cbi_wcomp = 0x0,
56 msc_proto_cbi_wocomp = 0x1,
57 msc_proto_bulk_only = 0x50
58};
59static const char *msc_protocol_strings[0x51] = {
60 "Control/Bulk/Interrupt protocol (with command completion interrupt)",
61 "Control/Bulk/Interrupt protocol (with no command completion interrupt)",
62 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 "Bulk-Only Transport"
68};
69
70
71static void
72usb_msc_destroy (usbdev_t *dev)
73{
Nico Huber445a3a02012-06-21 10:52:49 +020074 if (dev->data) {
75 if (MSC_INST (dev)->usbdisk_created && usbdisk_remove)
76 usbdisk_remove (dev);
77 free (dev->data);
78 }
Patrick Georgid21f68b2008-09-02 16:06:22 +000079 dev->data = 0;
80}
81
82static void
83usb_msc_poll (usbdev_t *dev)
84{
85}
86
87const int DEV_RESET = 0xff;
88const int GET_MAX_LUN = 0xfe;
89
90const unsigned int cbw_signature = 0x43425355;
91const unsigned int csw_signature = 0x53425355;
92
93typedef struct {
94 unsigned int dCBWSignature;
95 unsigned int dCBWTag;
96 unsigned int dCBWDataTransferLength;
97 unsigned char bmCBWFlags;
98 unsigned long bCBWLUN:4;
99 unsigned long:4;
100 unsigned long bCBWCBLength:5;
101 unsigned long:3;
102 unsigned char CBWCB[31 - 15];
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000103} __attribute__ ((packed)) cbw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000104
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000105typedef struct {
106 unsigned int dCSWSignature;
107 unsigned int dCSWTag;
108 unsigned int dCSWDataResidue;
109 unsigned char bCSWStatus;
110} __attribute__ ((packed)) csw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000111
Nico Huber79e1f2f2012-06-01 09:50:11 +0200112enum {
113 /*
114 * MSC commands can be
115 * successful,
116 * fail with proper response or
117 * fail totally, which results in detaching of the usb device.
118 * In the latter case the caller has to make sure, that he won't
119 * use the device any more.
120 */
121 MSC_COMMAND_OK = 0, MSC_COMMAND_FAIL, MSC_COMMAND_DETACHED
122};
123
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000124static int
125request_sense (usbdev_t *dev);
126
Nico Huber79e1f2f2012-06-01 09:50:11 +0200127static int
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000128reset_transport (usbdev_t *dev)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000129{
130 dev_req_t dr;
131 memset (&dr, 0, sizeof (dr));
132 dr.bmRequestType = 0;
133 dr.data_dir = host_to_device;
134#ifndef QEMU
135 dr.req_type = class_type;
136 dr.req_recp = iface_recp;
137#endif
138 dr.bRequest = DEV_RESET;
139 dr.wValue = 0;
140 dr.wIndex = 0;
141 dr.wLength = 0;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200142
143 /* if any of these fails, detach device, as we are lost */
144 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) ||
145 clear_stall (MSC_INST (dev)->bulk_in) ||
146 clear_stall (MSC_INST (dev)->bulk_out)) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700147 usb_debug ("Detaching unresponsive device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200148 usb_detach_device (dev->controller, dev->address);
149 return MSC_COMMAND_DETACHED;
150 }
151 /* return fail as we are only called in case of failure */
152 return MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000153}
154
155/* device may stall this command, so beware! */
156static int
157get_max_luns (usbdev_t *dev)
158{
159 unsigned char luns = 75;
160 dev_req_t dr;
161 dr.bmRequestType = 0;
162 dr.data_dir = device_to_host;
163#ifndef QEMU
164 dr.req_type = class_type;
165 dr.req_recp = iface_recp;
166#endif
167 dr.bRequest = GET_MAX_LUN;
168 dr.wValue = 0;
169 dr.wIndex = 0;
170 dr.wLength = 1;
171 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
172 luns = 0; // assume only 1 lun if req fails
173 }
174 return luns;
175}
176
Nico Huber43b9f322012-05-21 14:05:41 +0200177unsigned int tag;
178unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000179
180static void
181wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
182 int cmdlen)
183{
184 memset (cbw, 0, sizeof (cbw_t));
185
186 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200187 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000188 cbw->bCBWLUN = lun; // static value per device
189
190 cbw->dCBWDataTransferLength = datalen;
191 cbw->bmCBWFlags = dir;
192 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
193 cbw->bCBWCBLength = cmdlen;
194}
195
Nico Huber43b9f322012-05-21 14:05:41 +0200196static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000197get_csw (endpoint_t *ep, csw_t *csw)
198{
Nico Huber43b9f322012-05-21 14:05:41 +0200199 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000200 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200201 if (ep->dev->controller->bulk
202 (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200203 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200204 }
205 }
206 if (csw->dCSWTag != tag) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200207 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200208 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200209 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000210}
211
212static int
213execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200214 u8 *buf, int buflen, int residue_ok)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000215{
216 cbw_t cbw;
217 csw_t csw;
218
219 int always_succeed = 0;
220 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
221 always_succeed = 1;
222 }
223 wrap_cbw (&cbw, buflen, dir, cb, cblen);
224 if (dev->controller->
225 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200226 return reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000227 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000228 if (buflen > 0) {
229 if (dir == cbw_direction_data_in) {
230 if (dev->controller->
Nico Huberef88e102012-11-21 16:25:55 +0100231 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000232 clear_stall (MSC_INST (dev)->bulk_in);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000233 } else {
234 if (dev->controller->
Nico Huberef88e102012-11-21 16:25:55 +0100235 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000236 clear_stall (MSC_INST (dev)->bulk_out);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000237 }
238 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200239 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
240 if (ret) {
241 return ret;
242 } else if (always_succeed == 1) {
243 /* return success, regardless of message */
244 return MSC_COMMAND_OK;
245 } else if (csw.bCSWStatus == 2) {
246 /* phase error, reset transport */
247 return reset_transport (dev);
248 } else if (csw.bCSWStatus == 0) {
249 if ((csw.dCSWDataResidue == 0) || residue_ok)
250 /* no error, exit */
251 return MSC_COMMAND_OK;
252 else
253 /* missed some bytes */
254 return MSC_COMMAND_FAIL;
255 } else {
256 if (cb[0] == 0x03)
257 /* requesting sense failed, that's bad */
258 return MSC_COMMAND_FAIL;
259 /* error "check condition" or reserved error */
260 ret = request_sense (dev);
261 /* return fail or the status of request_sense if it's worse */
262 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000263 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000264}
265
266typedef struct {
267 unsigned char command; //0
268 unsigned char res1; //1
269 unsigned int block; //2-5
270 unsigned char res2; //6
271 unsigned short numblocks; //7-8
272 unsigned char res3; //9 - the block is 10 bytes long
273} __attribute__ ((packed)) cmdblock_t;
274
275typedef struct {
276 unsigned char command; //0
277 unsigned char res1; //1
278 unsigned char res2; //2
279 unsigned char res3; //3
280 unsigned char lun; //4
281 unsigned char res4; //5
282} __attribute__ ((packed)) cmdblock6_t;
283
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000284/**
285 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
286 * start and count from 512b units.
287 * Start and count must be aligned so that they match the native
288 * sector size.
289 *
290 * @param dev device to access
291 * @param start first sector to access
292 * @param n number of sectors to access
293 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
294 * @param buf buffer to read into or write from. Must be at least n*512 bytes
295 * @return 0 on success, 1 on failure
296 */
297int
298readwrite_blocks_512 (usbdev_t *dev, int start, int n,
299 cbw_direction dir, u8 *buf)
300{
301 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
302 return readwrite_blocks (dev, start / blocksize_divider,
303 n / blocksize_divider, dir, buf);
304}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000305
306/**
307 * Reads or writes a number of sequential blocks on a USB storage device.
308 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
309 * of at most 2TB. It assumes sectors of 512 bytes.
310 *
311 * @param dev device to access
312 * @param start first sector to access
313 * @param n number of sectors to access
314 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000315 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000316 * @return 0 on success, 1 on failure
317 */
318int
319readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
320{
321 cmdblock_t cb;
322 memset (&cb, 0, sizeof (cb));
323 if (dir == cbw_direction_data_in) {
324 // read
325 cb.command = 0x28;
326 } else {
327 // write
328 cb.command = 0x2a;
329 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000330 cb.block = htonl (start);
331 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000332
Patrick Georgid21f68b2008-09-02 16:06:22 +0000333 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200334 n * MSC_INST(dev)->blocksize, 0)
335 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000336}
337
338/* Only request it, we don't interpret it.
339 On certain errors, that's necessary to get devices out of
340 a special state called "Contingent Allegiance Condition" */
341static int
342request_sense (usbdev_t *dev)
343{
344 u8 buf[19];
345 cmdblock6_t cb;
346 memset (&cb, 0, sizeof (cb));
347 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000348
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000349 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200350 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000351}
352
353static int
354test_unit_ready (usbdev_t *dev)
355{
356 cmdblock6_t cb;
357 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
358 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200359 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000360}
361
362static int
363spin_up (usbdev_t *dev)
364{
365 cmdblock6_t cb;
366 memset (&cb, 0, sizeof (cb));
367 cb.command = 0x1b;
368 cb.lun = 1;
369 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200370 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000371}
372
Nico Huber79e1f2f2012-06-01 09:50:11 +0200373static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000374read_capacity (usbdev_t *dev)
375{
376 cmdblock_t cb;
377 memset (&cb, 0, sizeof (cb));
378 cb.command = 0x25; // read capacity
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800379 u32 buf[2];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000380
Gabe Black93ded592012-11-01 15:44:10 -0700381 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200382 int count = 0, ret;
383 while (count++ < 20) {
384 switch (ret = execute_command
385 (dev, cbw_direction_data_in, (u8 *) &cb,
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800386 sizeof (cb), (u8 *)buf, 8, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200387 case MSC_COMMAND_OK:
388 break;
389 case MSC_COMMAND_FAIL:
390 continue;
391 default: /* if it's worse return */
392 return ret;
393 }
394 break;
395 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000396 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000397 // 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 -0700398 usb_debug (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000399 MSC_INST (dev)->numblocks = 0xffffffff;
400 MSC_INST (dev)->blocksize = 512;
401 } else {
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800402 MSC_INST (dev)->numblocks = ntohl(buf[0]) + 1;
403 MSC_INST (dev)->blocksize = ntohl(buf[1]);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000404 }
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700405 usb_debug (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
Mathias Krausec4716b42011-06-08 15:36:55 +0200406 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200407 /* round down high block counts to avoid integer overflow */
408 MSC_INST (dev)->numblocks > 1000000
409 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200410 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200411 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000412}
413
414void
415usb_msc_init (usbdev_t *dev)
416{
417 int i, timeout;
418
Nico Huber445a3a02012-06-21 10:52:49 +0200419 /* init .data before setting .destroy */
420 dev->data = NULL;
421
Patrick Georgid21f68b2008-09-02 16:06:22 +0000422 dev->destroy = usb_msc_destroy;
423 dev->poll = usb_msc_poll;
424
425 configuration_descriptor_t *cd =
426 (configuration_descriptor_t *) dev->configuration;
427 interface_descriptor_t *interface =
428 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
429
Gabe Black93ded592012-11-01 15:44:10 -0700430 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000431 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700432 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000433 msc_protocol_strings[interface->bInterfaceProtocol]);
434
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000435
436 if (interface->bInterfaceProtocol != 0x50) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700437 usb_debug (" Protocol not supported.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000438 return;
439 }
440
441 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
442 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
443 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000444 /* 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 -0700445 usb_debug (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000446 return;
447 }
448
449 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000450 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100451 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000452
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000453 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000454 MSC_INST (dev)->bulk_in = 0;
455 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200456 MSC_INST (dev)->usbdisk_created = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000457
458 for (i = 1; i <= dev->num_endp; i++) {
459 if (dev->endpoints[i].endpoint == 0)
460 continue;
461 if (dev->endpoints[i].type != BULK)
462 continue;
463 if ((dev->endpoints[i].direction == IN)
464 && (MSC_INST (dev)->bulk_in == 0))
465 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
466 if ((dev->endpoints[i].direction == OUT)
467 && (MSC_INST (dev)->bulk_out == 0))
468 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
469 }
470
Nico Huber445a3a02012-06-21 10:52:49 +0200471 if (MSC_INST (dev)->bulk_in == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700472 usb_debug("couldn't find bulk-in endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200473 return;
474 }
475 if (MSC_INST (dev)->bulk_out == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700476 usb_debug("couldn't find bulk-out endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200477 return;
478 }
Gabe Black93ded592012-11-01 15:44:10 -0700479 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000480 MSC_INST (dev)->bulk_in->endpoint,
481 MSC_INST (dev)->bulk_out->endpoint);
482
Gabe Black93ded592012-11-01 15:44:10 -0700483 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000484
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700485 usb_debug (" Waiting for device to become ready...");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000486 timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Nico Huber79e1f2f2012-06-01 09:50:11 +0200487 while (timeout--) {
488 switch (test_unit_ready (dev)) {
489 case MSC_COMMAND_OK:
490 break;
491 case MSC_COMMAND_FAIL:
492 mdelay (100);
493 if (!(timeout % 10))
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700494 usb_debug (".");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200495 continue;
496 default: /* if it's worse return */
497 return;
498 }
499 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000500 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200501 if (timeout < 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700502 usb_debug ("timeout. Device not ready. Still trying...\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000503 } else {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700504 usb_debug ("ok.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000505 }
506
Gabe Black93ded592012-11-01 15:44:10 -0700507 usb_debug (" spin up");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000508 for (i = 0; i < 30; i++) {
Gabe Black93ded592012-11-01 15:44:10 -0700509 usb_debug (".");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200510 switch (spin_up (dev)) {
511 case MSC_COMMAND_OK:
Gabe Black93ded592012-11-01 15:44:10 -0700512 usb_debug (" OK.");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000513 break;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200514 case MSC_COMMAND_FAIL:
515 mdelay (100);
516 continue;
517 default: /* if it's worse return */
518 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000519 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200520 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000521 }
Gabe Black93ded592012-11-01 15:44:10 -0700522 usb_debug ("\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000523
Nico Huber445a3a02012-06-21 10:52:49 +0200524 if ((read_capacity (dev) == MSC_COMMAND_OK) && usbdisk_create) {
Patrick Georgi4727c072008-10-16 19:20:51 +0000525 usbdisk_create (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200526 MSC_INST (dev)->usbdisk_created = 1;
527 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000528}