blob: f68bee5bd37a7b17f907379c178ccd00763fa26c [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;
Duncan Laurie3a65d852013-09-12 13:27:15 -0700128/* Many USB3 devices do not work with large transfer requests.
129 * Limit the request size to 64KB chunks to ensure maximum compatibility. */
130const int MAX_CHUNK_BYTES = 1024 * 64;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000131
132const unsigned int cbw_signature = 0x43425355;
133const unsigned int csw_signature = 0x53425355;
134
135typedef struct {
136 unsigned int dCBWSignature;
137 unsigned int dCBWTag;
138 unsigned int dCBWDataTransferLength;
139 unsigned char bmCBWFlags;
140 unsigned long bCBWLUN:4;
141 unsigned long:4;
142 unsigned long bCBWCBLength:5;
143 unsigned long:3;
144 unsigned char CBWCB[31 - 15];
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000145} __attribute__ ((packed)) cbw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000146
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000147typedef struct {
148 unsigned int dCSWSignature;
149 unsigned int dCSWTag;
150 unsigned int dCSWDataResidue;
151 unsigned char bCSWStatus;
152} __attribute__ ((packed)) csw_t;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000153
Nico Huber79e1f2f2012-06-01 09:50:11 +0200154enum {
155 /*
156 * MSC commands can be
157 * successful,
158 * fail with proper response or
159 * fail totally, which results in detaching of the usb device.
160 * In the latter case the caller has to make sure, that he won't
161 * use the device any more.
162 */
163 MSC_COMMAND_OK = 0, MSC_COMMAND_FAIL, MSC_COMMAND_DETACHED
164};
165
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000166static int
167request_sense (usbdev_t *dev);
Aaron Durbina967f412013-06-06 16:14:21 -0500168static int
169request_sense_no_media (usbdev_t *dev);
Aaron Durbin1c20e382013-06-07 12:31:21 -0500170static void
171usb_msc_poll (usbdev_t *dev);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000172
Nico Huber79e1f2f2012-06-01 09:50:11 +0200173static int
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000174reset_transport (usbdev_t *dev)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000175{
176 dev_req_t dr;
177 memset (&dr, 0, sizeof (dr));
178 dr.bmRequestType = 0;
179 dr.data_dir = host_to_device;
180#ifndef QEMU
181 dr.req_type = class_type;
182 dr.req_recp = iface_recp;
183#endif
184 dr.bRequest = DEV_RESET;
185 dr.wValue = 0;
186 dr.wIndex = 0;
187 dr.wLength = 0;
Nico Huber79e1f2f2012-06-01 09:50:11 +0200188
189 /* if any of these fails, detach device, as we are lost */
Julius Wernere9738db2013-02-21 13:41:40 -0800190 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0 ||
Nico Huber79e1f2f2012-06-01 09:50:11 +0200191 clear_stall (MSC_INST (dev)->bulk_in) ||
192 clear_stall (MSC_INST (dev)->bulk_out)) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700193 usb_debug ("Detaching unresponsive device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200194 usb_detach_device (dev->controller, dev->address);
195 return MSC_COMMAND_DETACHED;
196 }
197 /* return fail as we are only called in case of failure */
198 return MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000199}
200
201/* device may stall this command, so beware! */
202static int
203get_max_luns (usbdev_t *dev)
204{
205 unsigned char luns = 75;
206 dev_req_t dr;
207 dr.bmRequestType = 0;
208 dr.data_dir = device_to_host;
209#ifndef QEMU
210 dr.req_type = class_type;
211 dr.req_recp = iface_recp;
212#endif
213 dr.bRequest = GET_MAX_LUN;
214 dr.wValue = 0;
215 dr.wIndex = 0;
216 dr.wLength = 1;
Julius Wernere9738db2013-02-21 13:41:40 -0800217 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns) < 0)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000218 luns = 0; // assume only 1 lun if req fails
Patrick Georgid21f68b2008-09-02 16:06:22 +0000219 return luns;
220}
221
Nico Huber43b9f322012-05-21 14:05:41 +0200222unsigned int tag;
223unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000224
225static void
226wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
227 int cmdlen)
228{
229 memset (cbw, 0, sizeof (cbw_t));
230
231 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200232 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000233 cbw->bCBWLUN = lun; // static value per device
234
235 cbw->dCBWDataTransferLength = datalen;
236 cbw->bmCBWFlags = dir;
237 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
238 cbw->bCBWCBLength = cmdlen;
239}
240
Nico Huber43b9f322012-05-21 14:05:41 +0200241static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000242get_csw (endpoint_t *ep, csw_t *csw)
243{
Julius Wernere9738db2013-02-21 13:41:40 -0800244 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000245 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200246 if (ep->dev->controller->bulk
Julius Wernere9738db2013-02-21 13:41:40 -0800247 (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200248 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200249 }
250 }
251 if (csw->dCSWTag != tag) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200252 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200253 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200254 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000255}
256
257static int
258execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200259 u8 *buf, int buflen, int residue_ok)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000260{
261 cbw_t cbw;
262 csw_t csw;
263
264 int always_succeed = 0;
265 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
266 always_succeed = 1;
267 }
268 wrap_cbw (&cbw, buflen, dir, cb, cblen);
269 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800270 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0) < 0) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200271 return reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000272 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000273 if (buflen > 0) {
274 if (dir == cbw_direction_data_in) {
275 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800276 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0) < 0)
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000277 clear_stall (MSC_INST (dev)->bulk_in);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000278 } else {
279 if (dev->controller->
Julius Wernere9738db2013-02-21 13:41:40 -0800280 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0) < 0)
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000281 clear_stall (MSC_INST (dev)->bulk_out);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000282 }
283 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200284 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
285 if (ret) {
286 return ret;
287 } else if (always_succeed == 1) {
288 /* return success, regardless of message */
289 return MSC_COMMAND_OK;
290 } else if (csw.bCSWStatus == 2) {
291 /* phase error, reset transport */
292 return reset_transport (dev);
293 } else if (csw.bCSWStatus == 0) {
294 if ((csw.dCSWDataResidue == 0) || residue_ok)
295 /* no error, exit */
296 return MSC_COMMAND_OK;
297 else
298 /* missed some bytes */
299 return MSC_COMMAND_FAIL;
300 } else {
301 if (cb[0] == 0x03)
302 /* requesting sense failed, that's bad */
303 return MSC_COMMAND_FAIL;
Aaron Durbina967f412013-06-06 16:14:21 -0500304 else if (cb[0] == 0)
305 /* If command was TEST UNIT READY determine if the
306 * device is of removable type indicating no media
307 * found. */
308 return request_sense_no_media (dev);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200309 /* error "check condition" or reserved error */
310 ret = request_sense (dev);
311 /* return fail or the status of request_sense if it's worse */
312 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000313 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000314}
315
316typedef struct {
317 unsigned char command; //0
318 unsigned char res1; //1
319 unsigned int block; //2-5
320 unsigned char res2; //6
321 unsigned short numblocks; //7-8
322 unsigned char res3; //9 - the block is 10 bytes long
323} __attribute__ ((packed)) cmdblock_t;
324
325typedef struct {
326 unsigned char command; //0
327 unsigned char res1; //1
328 unsigned char res2; //2
329 unsigned char res3; //3
330 unsigned char lun; //4
331 unsigned char res4; //5
332} __attribute__ ((packed)) cmdblock6_t;
333
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000334/**
335 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
336 * start and count from 512b units.
337 * Start and count must be aligned so that they match the native
338 * sector size.
339 *
340 * @param dev device to access
341 * @param start first sector to access
342 * @param n number of sectors to access
343 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
344 * @param buf buffer to read into or write from. Must be at least n*512 bytes
345 * @return 0 on success, 1 on failure
346 */
347int
348readwrite_blocks_512 (usbdev_t *dev, int start, int n,
349 cbw_direction dir, u8 *buf)
350{
351 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
352 return readwrite_blocks (dev, start / blocksize_divider,
353 n / blocksize_divider, dir, buf);
354}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000355
356/**
357 * Reads or writes a number of sequential blocks on a USB storage device.
358 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
359 * of at most 2TB. It assumes sectors of 512 bytes.
360 *
361 * @param dev device to access
362 * @param start first sector to access
363 * @param n number of sectors to access
364 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000365 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000366 * @return 0 on success, 1 on failure
367 */
368int
Duncan Laurie3a65d852013-09-12 13:27:15 -0700369readwrite_chunk (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000370{
371 cmdblock_t cb;
372 memset (&cb, 0, sizeof (cb));
373 if (dir == cbw_direction_data_in) {
374 // read
375 cb.command = 0x28;
376 } else {
377 // write
378 cb.command = 0x2a;
379 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000380 cb.block = htonl (start);
381 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000382
Patrick Georgid21f68b2008-09-02 16:06:22 +0000383 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200384 n * MSC_INST(dev)->blocksize, 0)
385 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000386}
387
Duncan Laurie3a65d852013-09-12 13:27:15 -0700388/**
389 * Reads or writes a number of sequential blocks on a USB storage device
390 * that is split into MAX_CHUNK_BYTES size requests.
391 *
392 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
393 * of at most 2TB. It assumes sectors of 512 bytes.
394 *
395 * @param dev device to access
396 * @param start first sector to access
397 * @param n number of sectors to access
398 * @param dir direction of access: cbw_direction_data_in == read,
399 * cbw_direction_data_out == write
400 * @param buf buffer to read into or write from.
401 * Must be at least n*sectorsize bytes
402 * @return 0 on success, 1 on failure
403 */
404int
405readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
406{
407 int chunk_size = MAX_CHUNK_BYTES / MSC_INST(dev)->blocksize;
408 int chunk;
409
410 /* Read as many full chunks as needed. */
411 for (chunk = 0; chunk < (n / chunk_size); chunk++) {
412 if (readwrite_chunk (dev, start + (chunk * chunk_size),
413 chunk_size, dir,
414 buf + (chunk * MAX_CHUNK_BYTES))
415 != MSC_COMMAND_OK)
416 return 1;
417 }
418
419 /* Read any remaining partial chunk at the end. */
420 if (n % chunk_size) {
421 if (readwrite_chunk (dev, start + (chunk * chunk_size),
422 n % chunk_size, dir,
423 buf + (chunk * MAX_CHUNK_BYTES))
424 != MSC_COMMAND_OK)
425 return 1;
426 }
427
428 return 0;
429}
430
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000431/* Only request it, we don't interpret it.
432 On certain errors, that's necessary to get devices out of
433 a special state called "Contingent Allegiance Condition" */
434static int
435request_sense (usbdev_t *dev)
436{
437 u8 buf[19];
438 cmdblock6_t cb;
439 memset (&cb, 0, sizeof (cb));
440 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000441
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000442 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200443 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000444}
445
Aaron Durbin1c20e382013-06-07 12:31:21 -0500446static int request_sense_no_media (usbdev_t *dev)
Aaron Durbina967f412013-06-06 16:14:21 -0500447{
448 u8 buf[19];
449 int ret;
450 cmdblock6_t cb;
451 memset (&cb, 0, sizeof (cb));
452 cb.command = 0x3;
453
454 ret = execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
455 sizeof (cb), buf, 19, 1);
456
457 if (ret)
458 return ret;
459
460 /* Check if sense key is set to NOT READY. */
461 if ((buf[2] & 0xf) != 2)
462 return MSC_COMMAND_FAIL;
463
464 /* Check if additional sense code is 0x3a. */
465 if (buf[12] != 0x3a)
466 return MSC_COMMAND_FAIL;
467
Aaron Durbin1c20e382013-06-07 12:31:21 -0500468 /* No media is present. Return MSC_COMMAND_OK while marking the disk
469 * not ready. */
470 usb_debug ("Empty media found.\n");
471 usb_msc_mark_not_ready (dev);
472 return MSC_COMMAND_OK;
Aaron Durbina967f412013-06-06 16:14:21 -0500473}
474
Patrick Georgid21f68b2008-09-02 16:06:22 +0000475static int
476test_unit_ready (usbdev_t *dev)
477{
478 cmdblock6_t cb;
479 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
480 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200481 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000482}
483
484static int
485spin_up (usbdev_t *dev)
486{
487 cmdblock6_t cb;
488 memset (&cb, 0, sizeof (cb));
489 cb.command = 0x1b;
490 cb.lun = 1;
491 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200492 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000493}
494
Nico Huber79e1f2f2012-06-01 09:50:11 +0200495static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000496read_capacity (usbdev_t *dev)
497{
498 cmdblock_t cb;
499 memset (&cb, 0, sizeof (cb));
500 cb.command = 0x25; // read capacity
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800501 u32 buf[2];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000502
Gabe Black93ded592012-11-01 15:44:10 -0700503 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200504 int count = 0, ret;
505 while (count++ < 20) {
506 switch (ret = execute_command
507 (dev, cbw_direction_data_in, (u8 *) &cb,
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800508 sizeof (cb), (u8 *)buf, 8, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200509 case MSC_COMMAND_OK:
510 break;
511 case MSC_COMMAND_FAIL:
512 continue;
513 default: /* if it's worse return */
514 return ret;
515 }
516 break;
517 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000518 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000519 // 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 -0700520 usb_debug (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000521 MSC_INST (dev)->numblocks = 0xffffffff;
522 MSC_INST (dev)->blocksize = 512;
523 } else {
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800524 MSC_INST (dev)->numblocks = ntohl(buf[0]) + 1;
525 MSC_INST (dev)->blocksize = ntohl(buf[1]);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000526 }
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700527 usb_debug (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
Mathias Krausec4716b42011-06-08 15:36:55 +0200528 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200529 /* round down high block counts to avoid integer overflow */
530 MSC_INST (dev)->numblocks > 1000000
531 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200532 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200533 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000534}
535
Aaron Durbin1c20e382013-06-07 12:31:21 -0500536static void
537usb_msc_test_unit_ready (usbdev_t *dev)
538{
539 int i;
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700540 time_t start_time_secs;
541 struct timeval tv;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500542 /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700543 const int timeout_secs = 30;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500544
545 usb_debug (" Waiting for device to become ready...");
546
547 /* Initially mark the device ready. */
548 usb_msc_mark_ready (dev);
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700549 gettimeofday (&tv, NULL);
550 start_time_secs = tv.tv_sec;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500551
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700552 while (tv.tv_sec - start_time_secs < timeout_secs) {
Aaron Durbin1c20e382013-06-07 12:31:21 -0500553 switch (test_unit_ready (dev)) {
554 case MSC_COMMAND_OK:
555 break;
556 case MSC_COMMAND_FAIL:
557 mdelay (100);
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700558 usb_debug (".");
559 gettimeofday (&tv, NULL);
Aaron Durbin1c20e382013-06-07 12:31:21 -0500560 continue;
561 default:
562 usb_debug ("detached. Device not ready.\n");
563 usb_msc_mark_detached (dev);
564 return;
565 }
566 break;
567 }
Shawn Nematbakhsh7ecc9122013-09-12 18:09:39 -0700568 if (!(tv.tv_sec - start_time_secs < timeout_secs)) {
Aaron Durbin1c20e382013-06-07 12:31:21 -0500569 usb_debug ("timeout. Device not ready.\n");
570 usb_msc_mark_not_ready (dev);
571 }
572
573 /* Don't bother spinning up the stroage device if the device is not
574 * ready. This can happen when empty card readers are present.
575 * Polling will pick it back up if readiness changes. */
576 if (!usb_msc_is_ready (dev))
577 return;
578
579 usb_debug ("ok.\n");
580
581 usb_debug (" spin up");
582 for (i = 0; i < 30; i++) {
583 usb_debug (".");
584 switch (spin_up (dev)) {
585 case MSC_COMMAND_OK:
586 usb_debug (" OK.");
587 break;
588 case MSC_COMMAND_FAIL:
589 mdelay (100);
590 continue;
591 default:
592 /* Device is no longer ready. */
593 usb_msc_mark_detached (dev);
594 return;
595 }
596 break;
597 }
598 usb_debug ("\n");
599
600 if (read_capacity (dev) != MSC_COMMAND_OK)
601 usb_msc_mark_not_ready (dev);
602}
603
Patrick Georgid21f68b2008-09-02 16:06:22 +0000604void
605usb_msc_init (usbdev_t *dev)
606{
Aaron Durbin1c20e382013-06-07 12:31:21 -0500607 int i;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000608
Nico Huber445a3a02012-06-21 10:52:49 +0200609 /* init .data before setting .destroy */
610 dev->data = NULL;
611
Patrick Georgid21f68b2008-09-02 16:06:22 +0000612 dev->destroy = usb_msc_destroy;
613 dev->poll = usb_msc_poll;
614
615 configuration_descriptor_t *cd =
616 (configuration_descriptor_t *) dev->configuration;
617 interface_descriptor_t *interface =
618 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
619
Gabe Black93ded592012-11-01 15:44:10 -0700620 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000621 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700622 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000623 msc_protocol_strings[interface->bInterfaceProtocol]);
624
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000625
626 if (interface->bInterfaceProtocol != 0x50) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700627 usb_debug (" Protocol not supported.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000628 return;
629 }
630
631 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
632 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
633 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000634 /* 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 -0700635 usb_debug (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000636 return;
637 }
638
639 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000640 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100641 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000642
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000643 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000644 MSC_INST (dev)->bulk_in = 0;
645 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200646 MSC_INST (dev)->usbdisk_created = 0;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500647 usb_msc_mark_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000648
649 for (i = 1; i <= dev->num_endp; i++) {
650 if (dev->endpoints[i].endpoint == 0)
651 continue;
652 if (dev->endpoints[i].type != BULK)
653 continue;
654 if ((dev->endpoints[i].direction == IN)
655 && (MSC_INST (dev)->bulk_in == 0))
656 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
657 if ((dev->endpoints[i].direction == OUT)
658 && (MSC_INST (dev)->bulk_out == 0))
659 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
660 }
661
Nico Huber445a3a02012-06-21 10:52:49 +0200662 if (MSC_INST (dev)->bulk_in == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700663 usb_debug("couldn't find bulk-in endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200664 return;
665 }
666 if (MSC_INST (dev)->bulk_out == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700667 usb_debug("couldn't find bulk-out endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200668 return;
669 }
Gabe Black93ded592012-11-01 15:44:10 -0700670 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000671 MSC_INST (dev)->bulk_in->endpoint,
672 MSC_INST (dev)->bulk_out->endpoint);
673
Gabe Black93ded592012-11-01 15:44:10 -0700674 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000675
Aaron Durbin1c20e382013-06-07 12:31:21 -0500676 /* Test if unit is ready. */
677 usb_msc_test_unit_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000678
Aaron Durbin1c20e382013-06-07 12:31:21 -0500679 /* Nothing to do if device is not ready. */
680 if (!usb_msc_is_ready (dev))
681 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000682
Aaron Durbin1c20e382013-06-07 12:31:21 -0500683 /* Create the disk. */
684 usb_msc_create_disk (dev);
685}
686
687static void
688usb_msc_poll (usbdev_t *dev)
689{
690 int prev_ready;
691
692 /* Nothing to do if device is detached. */
693 if (usb_msc_is_detached (dev))
694 return;
695
696 /* Handle ready transitions by keeping track of previous state . */
697 prev_ready = usb_msc_is_ready (dev);
698
699 usb_msc_test_unit_ready (dev);
700
701 if (!prev_ready && usb_msc_is_ready (dev)) {
702 usb_debug ("usb msc: not ready -> ready\n");
703 usb_msc_create_disk (dev);
704 } else if (prev_ready && !usb_msc_is_ready (dev)) {
705 usb_debug ("usb msc: ready -> not ready\n");
706 usb_msc_remove_disk (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200707 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000708}