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)
78 usb_msc_poll (usbdev_t *dev)
82 const int DEV_RESET = 0xff;
83 const int GET_MAX_LUN = 0xfe;
85 const unsigned int cbw_signature = 0x43425355;
86 const unsigned int csw_signature = 0x53425355;
89 unsigned int dCBWSignature;
91 unsigned int dCBWDataTransferLength;
92 unsigned char bmCBWFlags;
93 unsigned long bCBWLUN:4;
95 unsigned long bCBWCBLength:5;
97 unsigned char CBWCB[31 - 15];
98 } __attribute__ ((packed))
102 unsigned int dCSWSignature;
103 unsigned int dCSWTag;
104 unsigned int dCSWDataResidue;
105 unsigned char bCSWStatus;
106 } __attribute__ ((packed))
110 reset_transport (usbdev_t *dev)
113 memset (&dr, 0, sizeof (dr));
114 dr.bmRequestType = 0;
115 dr.data_dir = host_to_device;
117 dr.req_type = class_type;
118 dr.req_recp = iface_recp;
120 dr.bRequest = DEV_RESET;
124 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
125 clear_stall (MSC_INST (dev)->bulk_in);
126 clear_stall (MSC_INST (dev)->bulk_out);
129 /* device may stall this command, so beware! */
131 get_max_luns (usbdev_t *dev)
133 unsigned char luns = 75;
135 dr.bmRequestType = 0;
136 dr.data_dir = device_to_host;
138 dr.req_type = class_type;
139 dr.req_recp = iface_recp;
141 dr.bRequest = GET_MAX_LUN;
145 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) {
146 luns = 0; // assume only 1 lun if req fails
155 wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd,
158 memset (cbw, 0, sizeof (cbw_t));
160 cbw->dCBWSignature = cbw_signature;
161 cbw->dCBWTag = tag++;
162 cbw->bCBWLUN = lun; // static value per device
164 cbw->dCBWDataTransferLength = datalen;
165 cbw->bmCBWFlags = dir;
166 memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB));
167 cbw->bCBWCBLength = cmdlen;
171 get_csw (endpoint_t *ep, csw_t *csw)
173 ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1);
177 execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
183 int always_succeed = 0;
184 if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed
187 wrap_cbw (&cbw, buflen, dir, cb, cblen);
188 if (dev->controller->
189 bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) {
190 clear_stall (MSC_INST (dev)->bulk_out);
194 if (dir == cbw_direction_data_in) {
195 if (dev->controller->
196 bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
197 clear_stall (MSC_INST (dev)->bulk_in);
201 if (dev->controller->
202 bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
203 clear_stall (MSC_INST (dev)->bulk_out);
207 get_csw (MSC_INST (dev)->bulk_in, &csw);
208 if (always_succeed == 1) {
209 // return success, regardless of message
212 if (csw.bCSWStatus == 2) {
213 // phase error, reset transport
214 reset_transport (dev);
217 if (csw.bCSWStatus == 0) {
221 // error "check condition" or reserved error
226 unsigned char command; //0
227 unsigned char res1; //1
228 unsigned int block; //2-5
229 unsigned char res2; //6
230 unsigned short numblocks; //7-8
231 unsigned char res3; //9 - the block is 10 bytes long
232 } __attribute__ ((packed)) cmdblock_t;
235 unsigned char command; //0
236 unsigned char res1; //1
237 unsigned char res2; //2
238 unsigned char res3; //3
239 unsigned char lun; //4
240 unsigned char res4; //5
241 } __attribute__ ((packed)) cmdblock6_t;
245 * Reads or writes a number of sequential blocks on a USB storage device.
246 * As it uses the READ(10) SCSI-2 command, it's limited to storage devices
247 * of at most 2TB. It assumes sectors of 512 bytes.
249 * @param dev device to access
250 * @param start first sector to access
251 * @param n number of sectors to access
252 * @param dir direction of access: cbw_direction_data_in == read, cbw_direction_data_out == write
253 * @param buf buffer to read into or write from. Must be at least n*512 bytes
254 * @return 0 on success, 1 on failure
257 readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf)
260 memset (&cb, 0, sizeof (cb));
261 if (dir == cbw_direction_data_in) {
268 cb.block = ntohl (start);
269 cb.numblocks = ntohw (n);
270 return execute_command (dev, dir, (u8 *) &cb, sizeof (cb), buf,
275 test_unit_ready (usbdev_t *dev)
278 memset (&cb, 0, sizeof (cb)); // full initialization for T-U-R
279 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
284 spin_up (usbdev_t *dev)
287 memset (&cb, 0, sizeof (cb));
290 return execute_command (dev, cbw_direction_data_out, (u8 *) &cb,
295 read_capacity (usbdev_t *dev)
298 memset (&cb, 0, sizeof (cb));
299 cb.command = 0x25; // read capacity
302 while ((count++ < 20)
305 (dev, cbw_direction_data_in, (u8 *) &cb, sizeof (cb), buf,
308 // still not successful, assume 2tb in 512byte sectors, which is just the same garbage as any other number, but probably reasonable.
309 printf ("assuming 2TB in 512byte sectors as READ CAPACITY didn't answer.\n");
310 MSC_INST (dev)->numblocks = 0xffffffff;
311 MSC_INST (dev)->blocksize = 512;
313 MSC_INST (dev)->numblocks = ntohl (*(u32 *) buf) + 1;
314 MSC_INST (dev)->blocksize = ntohl (*(u32 *) (buf + 4));
316 printf (" has %d blocks sized %db\n", MSC_INST (dev)->numblocks,
317 MSC_INST (dev)->blocksize);
321 usb_msc_init (usbdev_t *dev)
325 dev->destroy = usb_msc_destroy;
326 dev->poll = usb_msc_poll;
328 configuration_descriptor_t *cd =
329 (configuration_descriptor_t *) dev->configuration;
330 interface_descriptor_t *interface =
331 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
333 printf (" it uses %s command set\n",
334 msc_subclass_strings[interface->bInterfaceSubClass]);
335 printf (" it uses %s protocol\n",
336 msc_protocol_strings[interface->bInterfaceProtocol]);
338 if ((interface->bInterfaceProtocol != 0x50)
339 || (interface->bInterfaceSubClass != 6)) {
340 /* Other protocols, such as ATAPI don't seem to be very popular. looks like ATAPI would be really easy to add, if necessary. */
341 printf (" Only SCSI over Bulk is supported.\n");
345 dev->data = malloc (sizeof (usbmsc_inst_t));
346 MSC_INST (dev)->bulk_in = 0;
347 MSC_INST (dev)->bulk_out = 0;
349 for (i = 1; i <= dev->num_endp; i++) {
350 if (dev->endpoints[i].endpoint == 0)
352 if (dev->endpoints[i].type != BULK)
354 if ((dev->endpoints[i].direction == IN)
355 && (MSC_INST (dev)->bulk_in == 0))
356 MSC_INST (dev)->bulk_in = &dev->endpoints[i];
357 if ((dev->endpoints[i].direction == OUT)
358 && (MSC_INST (dev)->bulk_out == 0))
359 MSC_INST (dev)->bulk_out = &dev->endpoints[i];
362 if (MSC_INST (dev)->bulk_in == 0)
363 fatal ("couldn't find bulk-in endpoint");
364 if (MSC_INST (dev)->bulk_out == 0)
365 fatal ("couldn't find bulk-out endpoint");
366 printf (" using endpoint %x as in, %x as out\n",
367 MSC_INST (dev)->bulk_in->endpoint,
368 MSC_INST (dev)->bulk_out->endpoint);
370 printf (" has %d luns\n", get_max_luns (dev) + 1);
372 printf (" Waiting for device to become ready... ");
374 while (test_unit_ready (dev) && --timeout) {
378 if (test_unit_ready (dev)) {
379 printf ("timeout. Device not ready. Still trying...\n");
385 for (i = 0; i < 30; i++) {
387 if (!spin_up (dev)) {
396 usbdisk_create (dev);