2 * This file is part of the libpayload project.
4 * Copyright (C) 2008 coresystems GmbH
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <arch/endian.h>
32 #include <usb/usbmsc.h>
33 #include <usb/usbdisk.h>
36 msc_subclass_rbc = 0x1,
37 msc_subclass_mmc2 = 0x2,
38 msc_subclass_qic157 = 0x3,
39 msc_subclass_ufi = 0x4,
40 msc_subclass_sff8070i = 0x5,
41 msc_subclass_scsitrans = 0x6
43 static const char *msc_subclass_strings[7] = {
53 msc_proto_cbi_wcomp = 0x0,
54 msc_proto_cbi_wocomp = 0x1,
55 msc_proto_bulk_only = 0x50
57 static const char *msc_protocol_strings[0x51] = {
58 "Control/Bulk/Interrupt protocol (with command completion interrupt)",
59 "Control/Bulk/Interrupt protocol (with no command completion interrupt)",
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 usb_msc_destroy (usbdev_t *dev)
79 usb_msc_poll (usbdev_t *dev)
83 const int DEV_RESET = 0xff;
84 const int GET_MAX_LUN = 0xfe;
86 const unsigned int cbw_signature = 0x43425355;
87 const unsigned int csw_signature = 0x53425355;
90 unsigned int dCBWSignature;
92 unsigned int dCBWDataTransferLength;
93 unsigned char bmCBWFlags;
94 unsigned long bCBWLUN:4;
96 unsigned long bCBWCBLength:5;
98 unsigned char CBWCB[31 - 15];
99 } __attribute__ ((packed))
103 unsigned int dCSWSignature;
104 unsigned int dCSWTag;
105 unsigned int dCSWDataResidue;
106 unsigned char bCSWStatus;
107 } __attribute__ ((packed))
111 reset_transport (usbdev_t *dev)
114 memset (&dr, 0, sizeof (dr));
115 dr.bmRequestType = 0;
116 dr.data_dir = host_to_device;
118 dr.req_type = class_type;
119 dr.req_recp = iface_recp;
121 dr.bRequest = DEV_RESET;
125 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
126 clear_stall (MSC_INST (dev)->bulk_in);
127 clear_stall (MSC_INST (dev)->bulk_out);
130 /* device may stall this command, so beware! */
132 get_max_luns (usbdev_t *dev)
134 unsigned char luns = 75;
136 dr.bmRequestType = 0;
137 dr.data_dir = device_to_host;
139 dr.req_type = class_type;
140 dr.req_recp = iface_recp;
142 dr.bRequest = GET_MAX_LUN;
146 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
147 luns = 0; // assume only 1 lun if req fails
156 wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
159 memset (cbw, 0, sizeof (cbw_t));
161 cbw->dCBWSignature = cbw_signature;
162 cbw->dCBWTag = tag++;
163 cbw->bCBWLUN = lun; // static value per device
165 cbw->dCBWDataTransferLength = datalen;
166 cbw->bmCBWFlags = dir;
167 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
168 cbw->bCBWCBLength = cmdlen;
172 get_csw (endpoint_t *ep, csw_t *csw)
174 ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1);
178 execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
184 int always_succeed = 0;
185 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
188 wrap_cbw (&cbw, buflen, dir, cb, cblen);
189 if (dev->controller->
190 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
191 clear_stall (MSC_INST (dev)->bulk_out);
195 if (dir == cbw_direction_data_in) {
196 if (dev->controller->
197 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
198 clear_stall (MSC_INST (dev)->bulk_in);
202 if (dev->controller->
203 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
204 clear_stall (MSC_INST (dev)->bulk_out);
208 get_csw (MSC_INST (dev)->bulk_in, &csw);
209 if (always_succeed == 1) {
210 // return success, regardless of message
213 if (csw.bCSWStatus == 2) {
214 // phase error, reset transport
215 reset_transport (dev);
218 if (csw.bCSWStatus == 0) {
222 // error "check condition" or reserved error
227 unsigned char command; //0
228 unsigned char res1; //1
229 unsigned int block; //2-5
230 unsigned char res2; //6
231 unsigned short numblocks; //7-8
232 unsigned char res3; //9 - the block is 10 bytes long
233 } __attribute__ ((packed)) cmdblock_t;
236 unsigned char command; //0
237 unsigned char res1; //1
238 unsigned char res2; //2
239 unsigned char res3; //3
240 unsigned char lun; //4
241 unsigned char res4; //5
242 } __attribute__ ((packed)) cmdblock6_t;
246 * Reads or writes a number of sequential blocks on a USB storage device.
247 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
248 * of at most 2TB. It assumes sectors of 512 bytes.
250 * @param dev device to access
251 * @param start first sector to access
252 * @param n number of sectors to access
253 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
254 * @param buf buffer to read into or write from. Must be at least n*512 bytes
255 * @return 0 on success, 1 on failure
258 readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
261 memset (&cb, 0, sizeof (cb));
262 if (dir == cbw_direction_data_in) {
269 cb.block = ntohl (start);
270 cb.numblocks = ntohw (n);
271 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
276 test_unit_ready (usbdev_t *dev)
279 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
280 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
285 spin_up (usbdev_t *dev)
288 memset (&cb, 0, sizeof (cb));
291 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
296 read_capacity (usbdev_t *dev)
299 memset (&cb, 0, sizeof (cb));
300 cb.command = 0x25; // read capacity
303 printf ("Reading capacity of mass storage device.\n");
305 while ((count++ < 20)
308 (dev, cbw_direction_data_in, (u8 *) &cb, sizeof (cb), buf,
311 // still not successful, assume 2tb in 512byte sectors, which is just the same garbage as any other number, but probably more usable.
312 printf ("Assuming 2TB in 512byte sectors as READ CAPACITY didn't answer.\n");
313 MSC_INST (dev)->numblocks = 0xffffffff;
314 MSC_INST (dev)->blocksize = 512;
316 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
317 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
319 printf (" has %d blocks sized %db\n", MSC_INST (dev)->numblocks,
320 MSC_INST (dev)->blocksize);
324 usb_msc_init (usbdev_t *dev)
328 dev->destroy = usb_msc_destroy;
329 dev->poll = usb_msc_poll;
331 configuration_descriptor_t *cd =
332 (configuration_descriptor_t *) dev->configuration;
333 interface_descriptor_t *interface =
334 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
336 printf (" it uses %s command set\n",
337 msc_subclass_strings[interface->bInterfaceSubClass]);
338 printf (" it uses %s protocol\n",
339 msc_protocol_strings[interface->bInterfaceProtocol]);
341 if ((interface->bInterfaceProtocol != 0x50)
342 || (interface->bInterfaceSubClass != 6)) {
343 /* Other protocols, such as ATAPI don't seem to be very popular. looks like ATAPI would be really easy to add, if necessary. */
344 printf (" Only SCSI over Bulk is supported.\n");
348 dev->data = malloc (sizeof (usbmsc_inst_t));
350 usb_fatal("Not enough memory for USB MSC device.\n");
352 MSC_INST (dev)->bulk_in = 0;
353 MSC_INST (dev)->bulk_out = 0;
355 for (i = 1; i <= dev->num_endp; i++) {
356 if (dev->endpoints[i].endpoint == 0)
358 if (dev->endpoints[i].type != BULK)
360 if ((dev->endpoints[i].direction == IN)
361 && (MSC_INST (dev)->bulk_in == 0))
362 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
363 if ((dev->endpoints[i].direction == OUT)
364 && (MSC_INST (dev)->bulk_out == 0))
365 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
368 if (MSC_INST (dev)->bulk_in == 0)
369 fatal ("couldn't find bulk-in endpoint");
370 if (MSC_INST (dev)->bulk_out == 0)
371 fatal ("couldn't find bulk-out endpoint");
372 printf (" using endpoint %x as in, %x as out\n",
373 MSC_INST (dev)->bulk_in->endpoint,
374 MSC_INST (dev)->bulk_out->endpoint);
376 printf (" has %d luns\n", get_max_luns (dev) + 1);
378 printf (" Waiting for device to become ready... ");
380 while (test_unit_ready (dev) && --timeout) {
384 if (test_unit_ready (dev)) {
385 printf ("timeout. Device not ready. Still trying...\n");
391 for (i = 0; i < 30; i++) {
393 if (!spin_up (dev)) {
403 usbdisk_create (dev);