blob: 2d28fbd12f1444f6e33e67ed153aafb7660a7132 [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
Aaron Durbin1c20e382013-06-07 12:31:21 -050070static inline void
71usb_msc_mark_ready (usbdev_t *dev)
72{
73 MSC_INST (dev)->ready = USB_MSC_READY;
74}
75
76static inline void
77usb_msc_mark_not_ready (usbdev_t *dev)
78{
79 MSC_INST (dev)->ready = USB_MSC_NOT_READY;
80}
81
82static inline void
83usb_msc_mark_detached (usbdev_t *dev)
84{
85 MSC_INST (dev)->ready = USB_MSC_DETACHED;
86}
87
88static inline int
89usb_msc_is_detached (usbdev_t *dev)
90{
91 return MSC_INST (dev)->ready == USB_MSC_DETACHED;
92}
93
94static inline int
95usb_msc_is_ready (usbdev_t *dev)
96{
97 return MSC_INST (dev)->ready == USB_MSC_READY;
98}
99
100static void
101usb_msc_create_disk (usbdev_t *dev)
102{
103 if (usbdisk_create) {
104 usbdisk_create (dev);
105 MSC_INST (dev)->usbdisk_created = 1;
106 }
107}
108
109static void
110usb_msc_remove_disk (usbdev_t *dev)
111{
112 if (MSC_INST (dev)->usbdisk_created && usbdisk_remove)
113 usbdisk_remove (dev);
114}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000115
116static void
117usb_msc_destroy (usbdev_t *dev)
118{
Nico Huber445a3a02012-06-21 10:52:49 +0200119 if (dev->data) {
Aaron Durbin1c20e382013-06-07 12:31:21 -0500120 usb_msc_remove_disk (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200121 free (dev->data);
122 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000123 dev->data = 0;
124}
125
Patrick Georgid21f68b2008-09-02 16:06:22 +0000126const int DEV_RESET = 0xff;
127const int GET_MAX_LUN = 0xfe;
128
129const unsigned int cbw_signature = 0x43425355;
130const unsigned int csw_signature = 0x53425355;
131
132typedef struct {
133 unsigned int dCBWSignature;
134 unsigned int dCBWTag;
135 unsigned int dCBWDataTransferLength;
136 unsigned char bmCBWFlags;
137 unsigned long bCBWLUN:4;
138 unsigned long:4;
139 unsigned long bCBWCBLength:5;
140 unsigned long:3;
141 unsigned char CBWCB[31 - 15];
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000142} __attribute__ ((packed)) cbw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000143
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000144typedef struct {
145 unsigned int dCSWSignature;
146 unsigned int dCSWTag;
147 unsigned int dCSWDataResidue;
148 unsigned char bCSWStatus;
149} __attribute__ ((packed)) csw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000150
Nico Huber79e1f2f2012-06-01 09:50:11 +0200151enum {
152 /*
153 * MSC commands can be
154 * successful,
155 * fail with proper response or
156 * fail totally, which results in detaching of the usb device.
157 * In the latter case the caller has to make sure, that he won't
158 * use the device any more.
159 */
160 MSC_COMMAND_OK = 0, MSC_COMMAND_FAIL, MSC_COMMAND_DETACHED
161};
162
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000163static int
164request_sense (usbdev_t *dev);
Aaron Durbina967f412013-06-06 16:14:21 -0500165static int
166request_sense_no_media (usbdev_t *dev);
Aaron Durbin1c20e382013-06-07 12:31:21 -0500167static void
168usb_msc_poll (usbdev_t *dev);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000169
Nico Huber79e1f2f2012-06-01 09:50:11 +0200170static int
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000171reset_transport (usbdev_t *dev)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000172{
173 dev_req_t dr;
174 memset (&dr, 0, sizeof (dr));
175 dr.bmRequestType = 0;
176 dr.data_dir = host_to_device;
177#ifndef QEMU
178 dr.req_type = class_type;
179 dr.req_recp = iface_recp;
180#endif
181 dr.bRequest = DEV_RESET;
182 dr.wValue = 0;
183 dr.wIndex = 0;
184 dr.wLength = 0;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200185
186 /* if any of these fails, detach device, as we are lost */
Julius Wernere9738db2013-02-21 13:41:40 -0800187 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0 ||
Nico Huber79e1f2f2012-06-01 09:50:11 +0200188 clear_stall (MSC_INST (dev)->bulk_in) ||
189 clear_stall (MSC_INST (dev)->bulk_out)) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700190 usb_debug ("Detaching unresponsive device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200191 usb_detach_device (dev->controller, dev->address);
192 return MSC_COMMAND_DETACHED;
193 }
194 /* return fail as we are only called in case of failure */
195 return MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000196}
197
198/* device may stall this command, so beware! */
199static int
200get_max_luns (usbdev_t *dev)
201{
202 unsigned char luns = 75;
203 dev_req_t dr;
204 dr.bmRequestType = 0;
205 dr.data_dir = device_to_host;
206#ifndef QEMU
207 dr.req_type = class_type;
208 dr.req_recp = iface_recp;
209#endif
210 dr.bRequest = GET_MAX_LUN;
211 dr.wValue = 0;
212 dr.wIndex = 0;
213 dr.wLength = 1;
Julius Wernere9738db2013-02-21 13:41:40 -0800214 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns) < 0)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000215 luns = 0; // assume only 1 lun if req fails
Patrick Georgid21f68b2008-09-02 16:06:22 +0000216 return luns;
217}
218
Nico Huber43b9f322012-05-21 14:05:41 +0200219unsigned int tag;
220unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000221
222static void
223wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
224 int cmdlen)
225{
226 memset (cbw, 0, sizeof (cbw_t));
227
228 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200229 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000230 cbw->bCBWLUN = lun; // static value per device
231
232 cbw->dCBWDataTransferLength = datalen;
233 cbw->bmCBWFlags = dir;
234 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
235 cbw->bCBWCBLength = cmdlen;
236}
237
Nico Huber43b9f322012-05-21 14:05:41 +0200238static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000239get_csw (endpoint_t *ep, csw_t *csw)
240{
Julius Wernere9738db2013-02-21 13:41:40 -0800241 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000242 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200243 if (ep->dev->controller->bulk
Julius Wernere9738db2013-02-21 13:41:40 -0800244 (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200245 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200246 }
247 }
248 if (csw->dCSWTag != tag) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200249 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200250 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200251 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000252}
253
254static int
255execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200256 u8 *buf, int buflen, int residue_ok)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000257{
258 cbw_t cbw;
259 csw_t csw;
260
261 int always_succeed = 0;
262 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
263 always_succeed = 1;
264 }
265 wrap_cbw (&cbw, buflen, dir, cb, cblen);
266 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800267 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0) < 0) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200268 return reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000269 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000270 if (buflen > 0) {
271 if (dir == cbw_direction_data_in) {
272 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800273 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0) < 0)
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000274 clear_stall (MSC_INST (dev)->bulk_in);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000275 } else {
276 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800277 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0) < 0)
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000278 clear_stall (MSC_INST (dev)->bulk_out);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000279 }
280 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200281 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
282 if (ret) {
283 return ret;
284 } else if (always_succeed == 1) {
285 /* return success, regardless of message */
286 return MSC_COMMAND_OK;
287 } else if (csw.bCSWStatus == 2) {
288 /* phase error, reset transport */
289 return reset_transport (dev);
290 } else if (csw.bCSWStatus == 0) {
291 if ((csw.dCSWDataResidue == 0) || residue_ok)
292 /* no error, exit */
293 return MSC_COMMAND_OK;
294 else
295 /* missed some bytes */
296 return MSC_COMMAND_FAIL;
297 } else {
298 if (cb[0] == 0x03)
299 /* requesting sense failed, that's bad */
300 return MSC_COMMAND_FAIL;
Aaron Durbina967f412013-06-06 16:14:21 -0500301 else if (cb[0] == 0)
302 /* If command was TEST UNIT READY determine if the
303 * device is of removable type indicating no media
304 * found. */
305 return request_sense_no_media (dev);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200306 /* error "check condition" or reserved error */
307 ret = request_sense (dev);
308 /* return fail or the status of request_sense if it's worse */
309 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000310 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000311}
312
313typedef struct {
314 unsigned char command; //0
315 unsigned char res1; //1
316 unsigned int block; //2-5
317 unsigned char res2; //6
318 unsigned short numblocks; //7-8
319 unsigned char res3; //9 - the block is 10 bytes long
320} __attribute__ ((packed)) cmdblock_t;
321
322typedef struct {
323 unsigned char command; //0
324 unsigned char res1; //1
325 unsigned char res2; //2
326 unsigned char res3; //3
327 unsigned char lun; //4
328 unsigned char res4; //5
329} __attribute__ ((packed)) cmdblock6_t;
330
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000331/**
332 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
333 * start and count from 512b units.
334 * Start and count must be aligned so that they match the native
335 * sector size.
336 *
337 * @param dev device to access
338 * @param start first sector to access
339 * @param n number of sectors to access
340 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
341 * @param buf buffer to read into or write from. Must be at least n*512 bytes
342 * @return 0 on success, 1 on failure
343 */
344int
345readwrite_blocks_512 (usbdev_t *dev, int start, int n,
346 cbw_direction dir, u8 *buf)
347{
348 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
349 return readwrite_blocks (dev, start / blocksize_divider,
350 n / blocksize_divider, dir, buf);
351}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000352
353/**
354 * Reads or writes a number of sequential blocks on a USB storage device.
355 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
356 * of at most 2TB. It assumes sectors of 512 bytes.
357 *
358 * @param dev device to access
359 * @param start first sector to access
360 * @param n number of sectors to access
361 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000362 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000363 * @return 0 on success, 1 on failure
364 */
365int
366readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
367{
368 cmdblock_t cb;
369 memset (&cb, 0, sizeof (cb));
370 if (dir == cbw_direction_data_in) {
371 // read
372 cb.command = 0x28;
373 } else {
374 // write
375 cb.command = 0x2a;
376 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000377 cb.block = htonl (start);
378 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000379
Patrick Georgid21f68b2008-09-02 16:06:22 +0000380 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200381 n * MSC_INST(dev)->blocksize, 0)
382 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000383}
384
385/* Only request it, we don't interpret it.
386 On certain errors, that's necessary to get devices out of
387 a special state called "Contingent Allegiance Condition" */
388static int
389request_sense (usbdev_t *dev)
390{
391 u8 buf[19];
392 cmdblock6_t cb;
393 memset (&cb, 0, sizeof (cb));
394 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000395
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000396 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200397 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000398}
399
Aaron Durbin1c20e382013-06-07 12:31:21 -0500400static int request_sense_no_media (usbdev_t *dev)
Aaron Durbina967f412013-06-06 16:14:21 -0500401{
402 u8 buf[19];
403 int ret;
404 cmdblock6_t cb;
405 memset (&cb, 0, sizeof (cb));
406 cb.command = 0x3;
407
408 ret = execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
409 sizeof (cb), buf, 19, 1);
410
411 if (ret)
412 return ret;
413
414 /* Check if sense key is set to NOT READY. */
415 if ((buf[2] & 0xf) != 2)
416 return MSC_COMMAND_FAIL;
417
418 /* Check if additional sense code is 0x3a. */
419 if (buf[12] != 0x3a)
420 return MSC_COMMAND_FAIL;
421
Aaron Durbin1c20e382013-06-07 12:31:21 -0500422 /* No media is present. Return MSC_COMMAND_OK while marking the disk
423 * not ready. */
424 usb_debug ("Empty media found.\n");
425 usb_msc_mark_not_ready (dev);
426 return MSC_COMMAND_OK;
Aaron Durbina967f412013-06-06 16:14:21 -0500427}
428
Patrick Georgid21f68b2008-09-02 16:06:22 +0000429static int
430test_unit_ready (usbdev_t *dev)
431{
432 cmdblock6_t cb;
433 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
434 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200435 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000436}
437
438static int
439spin_up (usbdev_t *dev)
440{
441 cmdblock6_t cb;
442 memset (&cb, 0, sizeof (cb));
443 cb.command = 0x1b;
444 cb.lun = 1;
445 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200446 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000447}
448
Nico Huber79e1f2f2012-06-01 09:50:11 +0200449static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000450read_capacity (usbdev_t *dev)
451{
452 cmdblock_t cb;
453 memset (&cb, 0, sizeof (cb));
454 cb.command = 0x25; // read capacity
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800455 u32 buf[2];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000456
Gabe Black93ded592012-11-01 15:44:10 -0700457 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200458 int count = 0, ret;
459 while (count++ < 20) {
460 switch (ret = execute_command
461 (dev, cbw_direction_data_in, (u8 *) &cb,
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800462 sizeof (cb), (u8 *)buf, 8, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200463 case MSC_COMMAND_OK:
464 break;
465 case MSC_COMMAND_FAIL:
466 continue;
467 default: /* if it's worse return */
468 return ret;
469 }
470 break;
471 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000472 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000473 // 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 -0700474 usb_debug (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000475 MSC_INST (dev)->numblocks = 0xffffffff;
476 MSC_INST (dev)->blocksize = 512;
477 } else {
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800478 MSC_INST (dev)->numblocks = ntohl(buf[0]) + 1;
479 MSC_INST (dev)->blocksize = ntohl(buf[1]);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000480 }
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700481 usb_debug (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
Mathias Krausec4716b42011-06-08 15:36:55 +0200482 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200483 /* round down high block counts to avoid integer overflow */
484 MSC_INST (dev)->numblocks > 1000000
485 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200486 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200487 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000488}
489
Aaron Durbin1c20e382013-06-07 12:31:21 -0500490static void
491usb_msc_test_unit_ready (usbdev_t *dev)
492{
493 int i;
494 /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
495 const int timeout = 30 * 10;
496
497 usb_debug (" Waiting for device to become ready...");
498
499 /* Initially mark the device ready. */
500 usb_msc_mark_ready (dev);
501
502 for (i = 0; i < timeout; i++) {
503 switch (test_unit_ready (dev)) {
504 case MSC_COMMAND_OK:
505 break;
506 case MSC_COMMAND_FAIL:
507 mdelay (100);
508 if (!(timeout % 10))
509 usb_debug (".");
510 continue;
511 default:
512 usb_debug ("detached. Device not ready.\n");
513 usb_msc_mark_detached (dev);
514 return;
515 }
516 break;
517 }
518 if (i >= timeout) {
519 usb_debug ("timeout. Device not ready.\n");
520 usb_msc_mark_not_ready (dev);
521 }
522
523 /* Don't bother spinning up the stroage device if the device is not
524 * ready. This can happen when empty card readers are present.
525 * Polling will pick it back up if readiness changes. */
526 if (!usb_msc_is_ready (dev))
527 return;
528
529 usb_debug ("ok.\n");
530
531 usb_debug (" spin up");
532 for (i = 0; i < 30; i++) {
533 usb_debug (".");
534 switch (spin_up (dev)) {
535 case MSC_COMMAND_OK:
536 usb_debug (" OK.");
537 break;
538 case MSC_COMMAND_FAIL:
539 mdelay (100);
540 continue;
541 default:
542 /* Device is no longer ready. */
543 usb_msc_mark_detached (dev);
544 return;
545 }
546 break;
547 }
548 usb_debug ("\n");
549
550 if (read_capacity (dev) != MSC_COMMAND_OK)
551 usb_msc_mark_not_ready (dev);
552}
553
Patrick Georgid21f68b2008-09-02 16:06:22 +0000554void
555usb_msc_init (usbdev_t *dev)
556{
Aaron Durbin1c20e382013-06-07 12:31:21 -0500557 int i;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000558
Nico Huber445a3a02012-06-21 10:52:49 +0200559 /* init .data before setting .destroy */
560 dev->data = NULL;
561
Patrick Georgid21f68b2008-09-02 16:06:22 +0000562 dev->destroy = usb_msc_destroy;
563 dev->poll = usb_msc_poll;
564
565 configuration_descriptor_t *cd =
566 (configuration_descriptor_t *) dev->configuration;
567 interface_descriptor_t *interface =
568 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
569
Gabe Black93ded592012-11-01 15:44:10 -0700570 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000571 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700572 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000573 msc_protocol_strings[interface->bInterfaceProtocol]);
574
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000575
576 if (interface->bInterfaceProtocol != 0x50) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700577 usb_debug (" Protocol not supported.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000578 return;
579 }
580
581 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
582 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
583 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000584 /* 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 -0700585 usb_debug (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000586 return;
587 }
588
589 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000590 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100591 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000592
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000593 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000594 MSC_INST (dev)->bulk_in = 0;
595 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200596 MSC_INST (dev)->usbdisk_created = 0;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500597 usb_msc_mark_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000598
599 for (i = 1; i <= dev->num_endp; i++) {
600 if (dev->endpoints[i].endpoint == 0)
601 continue;
602 if (dev->endpoints[i].type != BULK)
603 continue;
604 if ((dev->endpoints[i].direction == IN)
605 && (MSC_INST (dev)->bulk_in == 0))
606 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
607 if ((dev->endpoints[i].direction == OUT)
608 && (MSC_INST (dev)->bulk_out == 0))
609 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
610 }
611
Nico Huber445a3a02012-06-21 10:52:49 +0200612 if (MSC_INST (dev)->bulk_in == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700613 usb_debug("couldn't find bulk-in endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200614 return;
615 }
616 if (MSC_INST (dev)->bulk_out == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700617 usb_debug("couldn't find bulk-out endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200618 return;
619 }
Gabe Black93ded592012-11-01 15:44:10 -0700620 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000621 MSC_INST (dev)->bulk_in->endpoint,
622 MSC_INST (dev)->bulk_out->endpoint);
623
Gabe Black93ded592012-11-01 15:44:10 -0700624 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000625
Aaron Durbin1c20e382013-06-07 12:31:21 -0500626 /* Test if unit is ready. */
627 usb_msc_test_unit_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000628
Aaron Durbin1c20e382013-06-07 12:31:21 -0500629 /* Nothing to do if device is not ready. */
630 if (!usb_msc_is_ready (dev))
631 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000632
Aaron Durbin1c20e382013-06-07 12:31:21 -0500633 /* Create the disk. */
634 usb_msc_create_disk (dev);
635}
636
637static void
638usb_msc_poll (usbdev_t *dev)
639{
640 int prev_ready;
641
642 /* Nothing to do if device is detached. */
643 if (usb_msc_is_detached (dev))
644 return;
645
646 /* Handle ready transitions by keeping track of previous state . */
647 prev_ready = usb_msc_is_ready (dev);
648
649 usb_msc_test_unit_ready (dev);
650
651 if (!prev_ready && usb_msc_is_ready (dev)) {
652 usb_debug ("usb msc: not ready -> ready\n");
653 usb_msc_create_disk (dev);
654 } else if (prev_ready && !usb_msc_is_ready (dev)) {
655 usb_debug ("usb msc: ready -> not ready\n");
656 usb_msc_remove_disk (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200657 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000658}