blob: f1de4831703599e7ae8d400a5d2161348f3a526e [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 */
187 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) ||
188 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;
214 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
215 luns = 0; // assume only 1 lun if req fails
216 }
217 return luns;
218}
219
Nico Huber43b9f322012-05-21 14:05:41 +0200220unsigned int tag;
221unsigned char lun = 0;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000222
223static void
224wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
225 int cmdlen)
226{
227 memset (cbw, 0, sizeof (cbw_t));
228
229 cbw->dCBWSignature = cbw_signature;
Nico Huber43b9f322012-05-21 14:05:41 +0200230 cbw->dCBWTag = ++tag;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000231 cbw->bCBWLUN = lun; // static value per device
232
233 cbw->dCBWDataTransferLength = datalen;
234 cbw->bmCBWFlags = dir;
235 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
236 cbw->bCBWCBLength = cmdlen;
237}
238
Nico Huber43b9f322012-05-21 14:05:41 +0200239static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000240get_csw (endpoint_t *ep, csw_t *csw)
241{
Nico Huber43b9f322012-05-21 14:05:41 +0200242 if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000243 clear_stall (ep);
Nico Huber43b9f322012-05-21 14:05:41 +0200244 if (ep->dev->controller->bulk
245 (ep, sizeof (csw_t), (u8 *) csw, 1)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200246 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200247 }
248 }
249 if (csw->dCSWTag != tag) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200250 return reset_transport (ep->dev);
Nico Huber43b9f322012-05-21 14:05:41 +0200251 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200252 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000253}
254
255static int
256execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200257 u8 *buf, int buflen, int residue_ok)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000258{
259 cbw_t cbw;
260 csw_t csw;
261
262 int always_succeed = 0;
263 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
264 always_succeed = 1;
265 }
266 wrap_cbw (&cbw, buflen, dir, cb, cblen);
267 if (dev->controller->
268 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200269 return reset_transport (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000270 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000271 if (buflen > 0) {
272 if (dir == cbw_direction_data_in) {
273 if (dev->controller->
Nico Huberef88e102012-11-21 16:25:55 +0100274 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000275 clear_stall (MSC_INST (dev)->bulk_in);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000276 } else {
277 if (dev->controller->
Nico Huberef88e102012-11-21 16:25:55 +0100278 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0))
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000279 clear_stall (MSC_INST (dev)->bulk_out);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000280 }
281 }
Nico Huber79e1f2f2012-06-01 09:50:11 +0200282 int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
283 if (ret) {
284 return ret;
285 } else if (always_succeed == 1) {
286 /* return success, regardless of message */
287 return MSC_COMMAND_OK;
288 } else if (csw.bCSWStatus == 2) {
289 /* phase error, reset transport */
290 return reset_transport (dev);
291 } else if (csw.bCSWStatus == 0) {
292 if ((csw.dCSWDataResidue == 0) || residue_ok)
293 /* no error, exit */
294 return MSC_COMMAND_OK;
295 else
296 /* missed some bytes */
297 return MSC_COMMAND_FAIL;
298 } else {
299 if (cb[0] == 0x03)
300 /* requesting sense failed, that's bad */
301 return MSC_COMMAND_FAIL;
Aaron Durbina967f412013-06-06 16:14:21 -0500302 else if (cb[0] == 0)
303 /* If command was TEST UNIT READY determine if the
304 * device is of removable type indicating no media
305 * found. */
306 return request_sense_no_media (dev);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200307 /* error "check condition" or reserved error */
308 ret = request_sense (dev);
309 /* return fail or the status of request_sense if it's worse */
310 return ret ? ret : MSC_COMMAND_FAIL;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000311 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000312}
313
314typedef struct {
315 unsigned char command; //0
316 unsigned char res1; //1
317 unsigned int block; //2-5
318 unsigned char res2; //6
319 unsigned short numblocks; //7-8
320 unsigned char res3; //9 - the block is 10 bytes long
321} __attribute__ ((packed)) cmdblock_t;
322
323typedef struct {
324 unsigned char command; //0
325 unsigned char res1; //1
326 unsigned char res2; //2
327 unsigned char res3; //3
328 unsigned char lun; //4
329 unsigned char res4; //5
330} __attribute__ ((packed)) cmdblock6_t;
331
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000332/**
333 * Like readwrite_blocks, but for soft-sectors of 512b size. Converts the
334 * start and count from 512b units.
335 * Start and count must be aligned so that they match the native
336 * sector size.
337 *
338 * @param dev device to access
339 * @param start first sector to access
340 * @param n number of sectors to access
341 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
342 * @param buf buffer to read into or write from. Must be at least n*512 bytes
343 * @return 0 on success, 1 on failure
344 */
345int
346readwrite_blocks_512 (usbdev_t *dev, int start, int n,
347 cbw_direction dir, u8 *buf)
348{
349 int blocksize_divider = MSC_INST(dev)->blocksize / 512;
350 return readwrite_blocks (dev, start / blocksize_divider,
351 n / blocksize_divider, dir, buf);
352}
Patrick Georgid21f68b2008-09-02 16:06:22 +0000353
354/**
355 * Reads or writes a number of sequential blocks on a USB storage device.
356 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
357 * of at most 2TB. It assumes sectors of 512 bytes.
358 *
359 * @param dev device to access
360 * @param start first sector to access
361 * @param n number of sectors to access
362 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000363 * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes
Patrick Georgid21f68b2008-09-02 16:06:22 +0000364 * @return 0 on success, 1 on failure
365 */
366int
367readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
368{
369 cmdblock_t cb;
370 memset (&cb, 0, sizeof (cb));
371 if (dir == cbw_direction_data_in) {
372 // read
373 cb.command = 0x28;
374 } else {
375 // write
376 cb.command = 0x2a;
377 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000378 cb.block = htonl (start);
379 cb.numblocks = htonw (n);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000380
Patrick Georgid21f68b2008-09-02 16:06:22 +0000381 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200382 n * MSC_INST(dev)->blocksize, 0)
383 != MSC_COMMAND_OK ? 1 : 0;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000384}
385
386/* Only request it, we don't interpret it.
387 On certain errors, that's necessary to get devices out of
388 a special state called "Contingent Allegiance Condition" */
389static int
390request_sense (usbdev_t *dev)
391{
392 u8 buf[19];
393 cmdblock6_t cb;
394 memset (&cb, 0, sizeof (cb));
395 cb.command = 0x3;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000396
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000397 return execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200398 sizeof (cb), buf, 19, 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000399}
400
Aaron Durbin1c20e382013-06-07 12:31:21 -0500401static int request_sense_no_media (usbdev_t *dev)
Aaron Durbina967f412013-06-06 16:14:21 -0500402{
403 u8 buf[19];
404 int ret;
405 cmdblock6_t cb;
406 memset (&cb, 0, sizeof (cb));
407 cb.command = 0x3;
408
409 ret = execute_command (dev, cbw_direction_data_in, (u8 *) &cb,
410 sizeof (cb), buf, 19, 1);
411
412 if (ret)
413 return ret;
414
415 /* Check if sense key is set to NOT READY. */
416 if ((buf[2] & 0xf) != 2)
417 return MSC_COMMAND_FAIL;
418
419 /* Check if additional sense code is 0x3a. */
420 if (buf[12] != 0x3a)
421 return MSC_COMMAND_FAIL;
422
Aaron Durbin1c20e382013-06-07 12:31:21 -0500423 /* No media is present. Return MSC_COMMAND_OK while marking the disk
424 * not ready. */
425 usb_debug ("Empty media found.\n");
426 usb_msc_mark_not_ready (dev);
427 return MSC_COMMAND_OK;
Aaron Durbina967f412013-06-06 16:14:21 -0500428}
429
Patrick Georgid21f68b2008-09-02 16:06:22 +0000430static int
431test_unit_ready (usbdev_t *dev)
432{
433 cmdblock6_t cb;
434 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
435 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200436 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000437}
438
439static int
440spin_up (usbdev_t *dev)
441{
442 cmdblock6_t cb;
443 memset (&cb, 0, sizeof (cb));
444 cb.command = 0x1b;
445 cb.lun = 1;
446 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
Nico Huber79e1f2f2012-06-01 09:50:11 +0200447 sizeof (cb), 0, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000448}
449
Nico Huber79e1f2f2012-06-01 09:50:11 +0200450static int
Patrick Georgid21f68b2008-09-02 16:06:22 +0000451read_capacity (usbdev_t *dev)
452{
453 cmdblock_t cb;
454 memset (&cb, 0, sizeof (cb));
455 cb.command = 0x25; // read capacity
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800456 u32 buf[2];
Stefan Reinauerd233f362009-04-30 16:46:12 +0000457
Gabe Black93ded592012-11-01 15:44:10 -0700458 usb_debug ("Reading capacity of mass storage device.\n");
Nico Huber79e1f2f2012-06-01 09:50:11 +0200459 int count = 0, ret;
460 while (count++ < 20) {
461 switch (ret = execute_command
462 (dev, cbw_direction_data_in, (u8 *) &cb,
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800463 sizeof (cb), (u8 *)buf, 8, 0)) {
Nico Huber79e1f2f2012-06-01 09:50:11 +0200464 case MSC_COMMAND_OK:
465 break;
466 case MSC_COMMAND_FAIL:
467 continue;
468 default: /* if it's worse return */
469 return ret;
470 }
471 break;
472 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000473 if (count >= 20) {
Stefan Reinauerd233f362009-04-30 16:46:12 +0000474 // 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 -0700475 usb_debug (" assuming 2 TB with 512-byte sectors as READ CAPACITY didn't answer.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000476 MSC_INST (dev)->numblocks = 0xffffffff;
477 MSC_INST (dev)->blocksize = 512;
478 } else {
Gabe Black2c2c4fa2013-01-15 16:22:04 -0800479 MSC_INST (dev)->numblocks = ntohl(buf[0]) + 1;
480 MSC_INST (dev)->blocksize = ntohl(buf[1]);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000481 }
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700482 usb_debug (" %d %d-byte sectors (%d MB)\n", MSC_INST (dev)->numblocks,
Mathias Krausec4716b42011-06-08 15:36:55 +0200483 MSC_INST (dev)->blocksize,
Nico Huberc43e7362012-05-21 13:59:43 +0200484 /* round down high block counts to avoid integer overflow */
485 MSC_INST (dev)->numblocks > 1000000
486 ? (MSC_INST (dev)->numblocks / 1000) * MSC_INST (dev)->blocksize / 1000 :
Mathias Krausec4716b42011-06-08 15:36:55 +0200487 MSC_INST (dev)->numblocks * MSC_INST (dev)->blocksize / 1000 / 1000);
Nico Huber79e1f2f2012-06-01 09:50:11 +0200488 return MSC_COMMAND_OK;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000489}
490
Aaron Durbin1c20e382013-06-07 12:31:21 -0500491static void
492usb_msc_test_unit_ready (usbdev_t *dev)
493{
494 int i;
495 /* SCSI/ATA specs say we have to wait up to 30s. Ugh */
496 const int timeout = 30 * 10;
497
498 usb_debug (" Waiting for device to become ready...");
499
500 /* Initially mark the device ready. */
501 usb_msc_mark_ready (dev);
502
503 for (i = 0; i < timeout; i++) {
504 switch (test_unit_ready (dev)) {
505 case MSC_COMMAND_OK:
506 break;
507 case MSC_COMMAND_FAIL:
508 mdelay (100);
509 if (!(timeout % 10))
510 usb_debug (".");
511 continue;
512 default:
513 usb_debug ("detached. Device not ready.\n");
514 usb_msc_mark_detached (dev);
515 return;
516 }
517 break;
518 }
519 if (i >= timeout) {
520 usb_debug ("timeout. Device not ready.\n");
521 usb_msc_mark_not_ready (dev);
522 }
523
524 /* Don't bother spinning up the stroage device if the device is not
525 * ready. This can happen when empty card readers are present.
526 * Polling will pick it back up if readiness changes. */
527 if (!usb_msc_is_ready (dev))
528 return;
529
530 usb_debug ("ok.\n");
531
532 usb_debug (" spin up");
533 for (i = 0; i < 30; i++) {
534 usb_debug (".");
535 switch (spin_up (dev)) {
536 case MSC_COMMAND_OK:
537 usb_debug (" OK.");
538 break;
539 case MSC_COMMAND_FAIL:
540 mdelay (100);
541 continue;
542 default:
543 /* Device is no longer ready. */
544 usb_msc_mark_detached (dev);
545 return;
546 }
547 break;
548 }
549 usb_debug ("\n");
550
551 if (read_capacity (dev) != MSC_COMMAND_OK)
552 usb_msc_mark_not_ready (dev);
553}
554
Patrick Georgid21f68b2008-09-02 16:06:22 +0000555void
556usb_msc_init (usbdev_t *dev)
557{
Aaron Durbin1c20e382013-06-07 12:31:21 -0500558 int i;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000559
Nico Huber445a3a02012-06-21 10:52:49 +0200560 /* init .data before setting .destroy */
561 dev->data = NULL;
562
Patrick Georgid21f68b2008-09-02 16:06:22 +0000563 dev->destroy = usb_msc_destroy;
564 dev->poll = usb_msc_poll;
565
566 configuration_descriptor_t *cd =
567 (configuration_descriptor_t *) dev->configuration;
568 interface_descriptor_t *interface =
569 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
570
Gabe Black93ded592012-11-01 15:44:10 -0700571 usb_debug (" it uses %s command set\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000572 msc_subclass_strings[interface->bInterfaceSubClass]);
Gabe Black93ded592012-11-01 15:44:10 -0700573 usb_debug (" it uses %s protocol\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000574 msc_protocol_strings[interface->bInterfaceProtocol]);
575
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000576
577 if (interface->bInterfaceProtocol != 0x50) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700578 usb_debug (" Protocol not supported.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000579 return;
580 }
581
582 if ((interface->bInterfaceSubClass != 2) && // ATAPI 8020
583 (interface->bInterfaceSubClass != 5) && // ATAPI 8070
584 (interface->bInterfaceSubClass != 6)) { // SCSI
Patrick Georgid21f68b2008-09-02 16:06:22 +0000585 /* 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 -0700586 usb_debug (" Interface SubClass not supported.\n");
Patrick Georgid21f68b2008-09-02 16:06:22 +0000587 return;
588 }
589
590 dev->data = malloc (sizeof (usbmsc_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000591 if (!dev->data)
Patrick Georgi2e768e72011-11-04 11:50:03 +0100592 fatal("Not enough memory for USB MSC device.\n");
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000593
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000594 MSC_INST (dev)->protocol = interface->bInterfaceSubClass;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000595 MSC_INST (dev)->bulk_in = 0;
596 MSC_INST (dev)->bulk_out = 0;
Nico Huber445a3a02012-06-21 10:52:49 +0200597 MSC_INST (dev)->usbdisk_created = 0;
Aaron Durbin1c20e382013-06-07 12:31:21 -0500598 usb_msc_mark_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000599
600 for (i = 1; i <= dev->num_endp; i++) {
601 if (dev->endpoints[i].endpoint == 0)
602 continue;
603 if (dev->endpoints[i].type != BULK)
604 continue;
605 if ((dev->endpoints[i].direction == IN)
606 && (MSC_INST (dev)->bulk_in == 0))
607 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
608 if ((dev->endpoints[i].direction == OUT)
609 && (MSC_INST (dev)->bulk_out == 0))
610 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
611 }
612
Nico Huber445a3a02012-06-21 10:52:49 +0200613 if (MSC_INST (dev)->bulk_in == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700614 usb_debug("couldn't find bulk-in endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200615 return;
616 }
617 if (MSC_INST (dev)->bulk_out == 0) {
Dave Frodin6bf11cf2012-12-11 13:08:07 -0700618 usb_debug("couldn't find bulk-out endpoint");
Nico Huber445a3a02012-06-21 10:52:49 +0200619 return;
620 }
Gabe Black93ded592012-11-01 15:44:10 -0700621 usb_debug (" using endpoint %x as in, %x as out\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000622 MSC_INST (dev)->bulk_in->endpoint,
623 MSC_INST (dev)->bulk_out->endpoint);
624
Gabe Black93ded592012-11-01 15:44:10 -0700625 usb_debug (" has %d luns\n", get_max_luns (dev) + 1);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000626
Aaron Durbin1c20e382013-06-07 12:31:21 -0500627 /* Test if unit is ready. */
628 usb_msc_test_unit_ready (dev);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000629
Aaron Durbin1c20e382013-06-07 12:31:21 -0500630 /* Nothing to do if device is not ready. */
631 if (!usb_msc_is_ready (dev))
632 return;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000633
Aaron Durbin1c20e382013-06-07 12:31:21 -0500634 /* Create the disk. */
635 usb_msc_create_disk (dev);
636}
637
638static void
639usb_msc_poll (usbdev_t *dev)
640{
641 int prev_ready;
642
643 /* Nothing to do if device is detached. */
644 if (usb_msc_is_detached (dev))
645 return;
646
647 /* Handle ready transitions by keeping track of previous state . */
648 prev_ready = usb_msc_is_ready (dev);
649
650 usb_msc_test_unit_ready (dev);
651
652 if (!prev_ready && usb_msc_is_ready (dev)) {
653 usb_debug ("usb msc: not ready -> ready\n");
654 usb_msc_create_disk (dev);
655 } else if (prev_ready && !usb_msc_is_ready (dev)) {
656 usb_debug ("usb msc: ready -> not ready\n");
657 usb_msc_remove_disk (dev);
Nico Huber445a3a02012-06-21 10:52:49 +0200658 }
Patrick Georgid21f68b2008-09-02 16:06:22 +0000659}