blob: 0475123b187090aa5cf499d86d08b28e7b41c0a3 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-08-04 01:14:12 +02002 * Most of this source has been derived from the Linux USB
3 * project:
4 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
5 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
6 * (c) 1999 Michael Gee (michael@linuxspecific.com)
7 * (c) 2000 Yggdrasil Computing, Inc.
8 *
9 *
10 * Adapted for U-Boot:
11 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
Simon Glassacf277a2015-03-25 12:22:16 -060012 * Driver model conversion:
13 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000014 *
wdenk149dded2003-09-10 18:20:28 +000015 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020016 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000017 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020018 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000019 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000020 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020021 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +000022 */
23
24/* Note:
25 * Currently only the CBI transport protocoll has been implemented, and it
26 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
27 * transport protocoll may work as well.
28 */
wdenk149dded2003-09-10 18:20:28 +000029/*
30 * New Note:
31 * Support for USB Mass Storage Devices (BBB) has been added. It has
32 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000033 */
wdenkaffae2b2002-08-17 09:36:01 +000034
35
wdenkaffae2b2002-08-17 09:36:01 +000036#include <common.h>
37#include <command.h>
Simon Glassacf277a2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glass91557572015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass4fd074d2014-10-15 04:38:38 -060040#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glasscf92e052015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggersc9182612008-05-21 22:12:00 +020043#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
wdenkaffae2b2002-08-17 09:36:01 +000046
Grant Likely735dd972007-02-20 09:04:34 +010047#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000048#include <usb.h>
49
wdenk80885a92004-02-26 23:46:20 +000050#undef BBB_COMDAT_TRACE
51#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000052
wdenkaffae2b2002-08-17 09:36:01 +000053#include <scsi.h>
54/* direction table -- this indicates the direction of the data
55 * transfer for each command code -- a 1 indicates input
56 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040057static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000058 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
59 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
62};
63#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
64
Puneet Saxenaf5766132012-04-03 14:56:06 +053065static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010066static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000067
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010068static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000069
Simon Glass4101f682016-02-29 15:25:34 -070070static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
wdenkaffae2b2002-08-17 09:36:01 +000071
72struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010073typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
74typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000075
76struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010077 struct usb_device *pusb_dev; /* this usb_device */
78
79 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020080# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010081 unsigned char ifnum; /* interface number */
82 unsigned char ep_in; /* in endpoint */
83 unsigned char ep_out; /* out ....... */
84 unsigned char ep_int; /* interrupt . */
85 unsigned char subclass; /* as in overview */
86 unsigned char protocol; /* .............. */
87 unsigned char attention_done; /* force attn on first cmd */
88 unsigned short ip_data; /* interrupt data */
89 int action; /* what to do */
90 int ip_wanted; /* needed */
91 int *irq_handle; /* for USB int requests */
92 unsigned int irqpipe; /* pipe for release_irq */
93 unsigned char irqmaxp; /* max packed for irq Pipe */
94 unsigned char irqinterval; /* Intervall for IRQ Pipe */
95 ccb *srb; /* current srb */
96 trans_reset transport_reset; /* reset routine */
97 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000098};
99
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200100#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000101/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200102 * The U-Boot EHCI driver can handle any transfer length as long as there is
103 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
104 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000105 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200106#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200107#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200108#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200109#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000110
wdenkaffae2b2002-08-17 09:36:01 +0000111static struct us_data usb_stor[USB_MAX_STOR_DEV];
112
wdenk80885a92004-02-26 23:46:20 +0000113#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000114#define USB_STOR_TRANSPORT_FAILED -1
115#define USB_STOR_TRANSPORT_ERROR -2
116
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100117int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glass4101f682016-02-29 15:25:34 -0700118 struct blk_desc *dev_desc);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100119int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
120 struct us_data *ss);
Simon Glass4101f682016-02-29 15:25:34 -0700121static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700122 lbaint_t blkcnt, void *buffer);
Simon Glass4101f682016-02-29 15:25:34 -0700123static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700124 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000125void uhci_show_temp_int_td(void);
126
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000127#ifdef CONFIG_PARTITIONS
Simon Glass4101f682016-02-29 15:25:34 -0700128struct blk_desc *usb_stor_get_dev(int index)
wdenkaffae2b2002-08-17 09:36:01 +0000129{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200130 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000131}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000132#endif
wdenkaffae2b2002-08-17 09:36:01 +0000133
Kim Phillips199adb62012-10-29 13:34:32 +0000134static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000135{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200136 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000137}
138
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100139/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200140 * show info on storage devices; 'usb start/init' must be invoked earlier
141 * as we only retrieve structures populated during devices initialization
142 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100143int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200144{
Simon Glass9807c3b2016-02-29 15:25:54 -0700145 int count = 0;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200146 int i;
147
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100148 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200149 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100150 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200151 dev_print(&usb_dev_desc[i]);
152 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100153 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100154 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700155
Simon Glass9807c3b2016-02-29 15:25:54 -0700156 if (!count) {
157 printf("No storage devices, perhaps not 'usb start'ed..?\n");
158 return 1;
159 }
160
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100161 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200162}
163
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200164static unsigned int usb_get_max_lun(struct us_data *us)
165{
166 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530167 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200168 len = usb_control_msg(us->pusb_dev,
169 usb_rcvctrlpipe(us->pusb_dev, 0),
170 US_BBB_GET_MAX_LUN,
171 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
172 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530173 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200174 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530175 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530176 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200177}
178
Simon Glass9807c3b2016-02-29 15:25:54 -0700179static int usb_stor_probe_device(struct usb_device *udev)
Simon Glass91557572015-03-25 12:22:15 -0600180{
Simon Glass9807c3b2016-02-29 15:25:54 -0700181 int lun, max_lun;
182 int start;
183
184 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600185 return -ENOENT; /* no more devices available */
186
Simon Glassc89e79d2016-02-29 15:25:53 -0700187 /* We don't have space to even probe if we hit the maximum */
188 if (usb_max_devs == USB_MAX_STOR_DEV) {
189 printf("max USB Storage Device reached: %d stopping\n",
190 usb_max_devs);
191 return -ENOSPC;
192 }
193
Simon Glass91557572015-03-25 12:22:15 -0600194 debug("\n\nProbing for storage\n");
Simon Glass9807c3b2016-02-29 15:25:54 -0700195 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
196 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600197
Simon Glass9807c3b2016-02-29 15:25:54 -0700198 /*
199 * OK, it's a storage device. Iterate over its LUNs and populate
200 * usb_dev_desc'
201 */
202 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600203
Simon Glass9807c3b2016-02-29 15:25:54 -0700204 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
205 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
206 lun++) {
207 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600208
Simon Glass9807c3b2016-02-29 15:25:54 -0700209 blkdev = &usb_dev_desc[usb_max_devs];
210 memset(blkdev, '\0', sizeof(struct blk_desc));
211 blkdev->if_type = IF_TYPE_USB;
212 blkdev->devnum = usb_max_devs;
213 blkdev->part_type = PART_TYPE_UNKNOWN;
214 blkdev->target = 0xff;
215 blkdev->type = DEV_TYPE_UNKNOWN;
216 blkdev->block_read = usb_stor_read;
217 blkdev->block_write = usb_stor_write;
218 blkdev->lun = lun;
219 blkdev->priv = udev;
220
221 if (usb_stor_get_info(udev, &usb_stor[start],
222 &usb_dev_desc[usb_max_devs]) == 1) {
223 usb_max_devs++;
224 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600225 }
226 }
227
Simon Glass91557572015-03-25 12:22:15 -0600228 return 0;
229}
230
231void usb_stor_reset(void)
232{
233 usb_max_devs = 0;
234}
235
Simon Glassacf277a2015-03-25 12:22:16 -0600236#ifndef CONFIG_DM_USB
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100237/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200238 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000239 * to the user if mode = 1
240 * returns current device or -1 if no
241 */
242int usb_stor_scan(int mode)
243{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600244 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000245
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100246 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200247 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100248
wdenkaffae2b2002-08-17 09:36:01 +0000249 usb_disable_asynch(1); /* asynch transfer not allowed */
250
Simon Glass91557572015-03-25 12:22:15 -0600251 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100252 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600253 struct usb_device *dev;
254
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100255 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530256 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600257 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000258 break;
wdenkaffae2b2002-08-17 09:36:01 +0000259 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200260
wdenkaffae2b2002-08-17 09:36:01 +0000261 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200262 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100263 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000264 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100265 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000266}
Simon Glassacf277a2015-03-25 12:22:16 -0600267#endif
wdenkaffae2b2002-08-17 09:36:01 +0000268
269static int usb_stor_irq(struct usb_device *dev)
270{
271 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100272 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000273
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100274 if (us->ip_wanted)
275 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000276 return 0;
277}
278
279
Vivek Gautamceb49722013-04-12 16:34:33 +0530280#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000281
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100282static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000283{
284 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100285 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
286 for (i = 0; i < 12; i++)
287 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000288 printf("\n");
289}
290
291static void display_int_status(unsigned long tmp)
292{
293 printf("Status: %s %s %s %s %s %s %s\n",
294 (tmp & USB_ST_ACTIVE) ? "Active" : "",
295 (tmp & USB_ST_STALLED) ? "Stalled" : "",
296 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
297 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
298 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
299 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
300 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
301}
302#endif
303/***********************************************************************
304 * Data transfer routines
305 ***********************************************************************/
306
307static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
308{
309 int max_size;
310 int this_xfer;
311 int result;
312 int partial;
313 int maxtry;
314 int stat;
315
316 /* determine the maximum packet size for these transfers */
317 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
318
319 /* while we have data left to transfer */
320 while (length) {
321
322 /* calculate how long this will be -- maximum or a remainder */
323 this_xfer = length > max_size ? max_size : length;
324 length -= this_xfer;
325
326 /* setup the retry counter */
327 maxtry = 10;
328
329 /* set up the transfer loop */
330 do {
331 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600332 debug("Bulk xfer 0x%lx(%d) try #%d\n",
333 (ulong)map_to_sysmem(buf), this_xfer,
334 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000335 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100336 this_xfer, &partial,
337 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530338 debug("bulk_msg returned %d xferred %d/%d\n",
339 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100340 if (us->pusb_dev->status != 0) {
341 /* if we stall, we need to clear it before
342 * we go on
343 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530344#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000345 display_int_status(us->pusb_dev->status);
346#endif
347 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530348 debug("stalled ->clearing endpoint" \
349 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000350 stat = us->pusb_dev->status;
351 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100352 us->pusb_dev->status = stat;
353 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530354 debug("bulk transferred" \
355 "with error %lX," \
356 " but data ok\n",
357 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000358 return 0;
359 }
360 else
361 return result;
362 }
363 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530364 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000365 return result;
366 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530367 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100368 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530369 debug(" %ld, but data ok\n",
370 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000371 return 0;
372 }
373 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530374 debug(" %ld, data %d\n",
375 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000376 if (!maxtry--)
377 return result;
378 }
379 /* update to show what data was transferred */
380 this_xfer -= partial;
381 buf += partial;
382 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100383 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000384 }
385
386 /* if we get here, we're done and successful */
387 return 0;
388}
389
wdenk149dded2003-09-10 18:20:28 +0000390static int usb_stor_BBB_reset(struct us_data *us)
391{
392 int result;
393 unsigned int pipe;
394
395 /*
396 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
397 *
398 * For Reset Recovery the host shall issue in the following order:
399 * a) a Bulk-Only Mass Storage Reset
400 * b) a Clear Feature HALT to the Bulk-In endpoint
401 * c) a Clear Feature HALT to the Bulk-Out endpoint
402 *
403 * This is done in 3 steps.
404 *
405 * If the reset doesn't succeed, the device should be port reset.
406 *
407 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
408 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530409 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100410 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
411 US_BBB_RESET,
412 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000413 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200414
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100415 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530416 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000417 return -1;
418 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200419
wdenk149dded2003-09-10 18:20:28 +0000420 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000421 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530422 debug("BBB_reset result %d: status %lX reset\n",
423 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000424 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
425 result = usb_clear_halt(us->pusb_dev, pipe);
426 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000427 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530428 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
429 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000430 /* long wait for reset */
431 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
432 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000433 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530434 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
435 result, us->pusb_dev->status);
436 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000437 return 0;
438}
439
wdenkaffae2b2002-08-17 09:36:01 +0000440/* FIXME: this reset function doesn't really reset the port, and it
441 * should. Actually it should probably do what it's doing here, and
442 * reset the port physically
443 */
444static int usb_stor_CB_reset(struct us_data *us)
445{
446 unsigned char cmd[12];
447 int result;
448
Vivek Gautamceb49722013-04-12 16:34:33 +0530449 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100450 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000451 cmd[0] = SCSI_SEND_DIAG;
452 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100453 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
454 US_CBI_ADSC,
455 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
456 0, us->ifnum, cmd, sizeof(cmd),
457 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000458
459 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000460 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530461 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
462 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000463 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
464 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
465
Vivek Gautamceb49722013-04-12 16:34:33 +0530466 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000467 return 0;
468}
469
wdenk149dded2003-09-10 18:20:28 +0000470/*
471 * Set up the command for a BBB device. Note that the actual SCSI
472 * command is copied into cbw.CBWCDB.
473 */
Kim Phillips199adb62012-10-29 13:34:32 +0000474static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000475{
476 int result;
477 int actlen;
478 int dir_in;
479 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600480 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000481
482 dir_in = US_DIRECTION(srb->cmd[0]);
483
484#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530485 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100486 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
487 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000488 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100489 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000490 printf("cmd[%d] %#x ", result, srb->cmd[result]);
491 printf("\n");
492 }
493#endif
494 /* sanity checks */
495 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530496 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000497 return -1;
498 }
499
500 /* always OUT to the ep */
501 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
502
Puneet Saxenaf5766132012-04-03 14:56:06 +0530503 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
504 cbw->dCBWTag = cpu_to_le32(CBWTag++);
505 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
506 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
507 cbw->bCBWLUN = srb->lun;
508 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000509 /* copy the command data into the CBW command data buffer */
510 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300511
Puneet Saxenaf5766132012-04-03 14:56:06 +0530512 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
513 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100514 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000515 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530516 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000517 return result;
518}
519
wdenkaffae2b2002-08-17 09:36:01 +0000520/* FIXME: we also need a CBI_command which sets up the completion
521 * interrupt, and waits for it
522 */
Kim Phillips199adb62012-10-29 13:34:32 +0000523static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000524{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200525 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100526 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000527 unsigned int pipe;
528 unsigned long status;
529
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100530 retry = 5;
531 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000532
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100533 if (dir_in)
534 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
535 else
536 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
537
538 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530539 debug("CBI gets a command: Try %d\n", 5 - retry);
540#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000541 usb_show_srb(srb);
542#endif
543 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100544 result = usb_control_msg(us->pusb_dev,
545 usb_sndctrlpipe(us->pusb_dev , 0),
546 US_CBI_ADSC,
547 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000548 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100549 srb->cmd, srb->cmdlen,
550 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530551 debug("CB_transport: control msg returned %d, status %lX\n",
552 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000553 /* check the return code for the command */
554 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100555 if (us->pusb_dev->status & USB_ST_STALLED) {
556 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530557 debug(" stall during command found," \
558 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100559 usb_clear_halt(us->pusb_dev,
560 usb_sndctrlpipe(us->pusb_dev, 0));
561 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000562 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530563 debug(" error during command %02X" \
564 " Stat = %lX\n", srb->cmd[0],
565 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000566 return result;
567 }
568 /* transfer the data payload for this command, if one exists*/
569
Vivek Gautamceb49722013-04-12 16:34:33 +0530570 debug("CB_transport: control msg returned %d," \
571 " direction is %s to go 0x%lx\n", result,
572 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000573 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100574 result = us_one_transfer(us, pipe, (char *)srb->pdata,
575 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530576 debug("CBI attempted to transfer data," \
577 " result is %d status %lX, len %d\n",
578 result, us->pusb_dev->status,
579 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100580 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000581 break;
582 } /* if (srb->datalen) */
583 else
584 break;
585 }
586 /* return result */
587
588 return result;
589}
590
591
Kim Phillips199adb62012-10-29 13:34:32 +0000592static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000593{
594 int timeout;
595
wdenk80885a92004-02-26 23:46:20 +0000596 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100597 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000598 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
599 timeout = 1000;
600 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300601 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000602 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000603 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000604 }
605 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100606 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000607 us->ip_wanted = 0;
608 return USB_STOR_TRANSPORT_ERROR;
609 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530610 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
611 us->ip_data, us->pusb_dev->irq_act_len,
612 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000613 /* UFI gives us ASC and ASCQ, like a request sense */
614 if (us->subclass == US_SC_UFI) {
615 if (srb->cmd[0] == SCSI_REQ_SENSE ||
616 srb->cmd[0] == SCSI_INQUIRY)
617 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000618 else if (us->ip_data)
619 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000620 else
wdenk80885a92004-02-26 23:46:20 +0000621 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000622 }
623 /* otherwise, we interpret the data normally */
624 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000625 case 0x0001:
626 return USB_STOR_TRANSPORT_GOOD;
627 case 0x0002:
628 return USB_STOR_TRANSPORT_FAILED;
629 default:
630 return USB_STOR_TRANSPORT_ERROR;
631 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000632 return USB_STOR_TRANSPORT_ERROR;
633}
634
635#define USB_TRANSPORT_UNKNOWN_RETRY 5
636#define USB_TRANSPORT_NOT_READY_RETRY 10
637
wdenk149dded2003-09-10 18:20:28 +0000638/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000639static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000640{
641 int result;
642
643 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100644 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000645 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000646 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000647 return result;
648}
649
Kim Phillips199adb62012-10-29 13:34:32 +0000650static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000651{
652 int result, retry;
653 int dir_in;
654 int actlen, data_actlen;
655 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600656 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000657#ifdef BBB_XPORT_TRACE
658 unsigned char *ptr;
659 int index;
660#endif
661
662 dir_in = US_DIRECTION(srb->cmd[0]);
663
664 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530665 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000666 result = usb_stor_BBB_comdat(srb, us);
667 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530668 debug("failed to send CBW status %ld\n",
669 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000670 usb_stor_BBB_reset(us);
671 return USB_STOR_TRANSPORT_FAILED;
672 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200673 if (!(us->flags & USB_READY))
674 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000675 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
676 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
677 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000678 data_actlen = 0;
679 /* no data, go immediately to the STATUS phase */
680 if (srb->datalen == 0)
681 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530682 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000683 if (dir_in)
684 pipe = pipein;
685 else
686 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300687
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100688 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
689 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000690 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100691 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530692 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000693 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100694 result = usb_stor_BBB_clear_endpt_stall(us,
695 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000696 if (result >= 0)
697 /* continue on to STATUS phase */
698 goto st;
699 }
700 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530701 debug("usb_bulk_msg error status %ld\n",
702 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000703 usb_stor_BBB_reset(us);
704 return USB_STOR_TRANSPORT_FAILED;
705 }
706#ifdef BBB_XPORT_TRACE
707 for (index = 0; index < data_actlen; index++)
708 printf("pdata[%d] %#x ", index, srb->pdata[index]);
709 printf("\n");
710#endif
711 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100712st:
wdenk149dded2003-09-10 18:20:28 +0000713 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100714again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530715 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530716 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200717 &actlen, USB_CNTL_TIMEOUT*5);
718
wdenk149dded2003-09-10 18:20:28 +0000719 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100720 if ((result < 0) && (retry < 1) &&
721 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530722 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000723 /* clear the STALL on the endpoint */
724 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
725 if (result >= 0 && (retry++ < 1))
726 /* do a retry */
727 goto again;
728 }
729 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530730 debug("usb_bulk_msg error status %ld\n",
731 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000732 usb_stor_BBB_reset(us);
733 return USB_STOR_TRANSPORT_FAILED;
734 }
735#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530736 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000737 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
738 printf("ptr[%d] %#x ", index, ptr[index]);
739 printf("\n");
740#endif
741 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530742 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000743 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
744 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530745 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530746 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000747 usb_stor_BBB_reset(us);
748 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530749 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530750 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000751 usb_stor_BBB_reset(us);
752 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530753 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530754 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000755 usb_stor_BBB_reset(us);
756 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530757 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530758 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000759 usb_stor_BBB_reset(us);
760 return USB_STOR_TRANSPORT_FAILED;
761 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530762 debug("transferred %dB instead of %ldB\n",
763 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000764 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530765 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530766 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000767 return USB_STOR_TRANSPORT_FAILED;
768 }
769
770 return result;
771}
772
Kim Phillips199adb62012-10-29 13:34:32 +0000773static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000774{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100775 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000776 ccb *psrb;
777 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100778 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000779
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200780 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100781 status = USB_STOR_TRANSPORT_GOOD;
782 retry = 0;
783 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000784 /* issue the command */
785do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100786 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530787 debug("command / Data returned %d, status %lX\n",
788 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000789 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100790 if (us->protocol == US_PR_CBI) {
791 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000792 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100793 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530794 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000795 return status;
796 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100797 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
798 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
799 if (!us->ip_data) {
800 /* if the status is good, report it */
801 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530802 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000803 return status;
804 }
805 }
806 }
807 /* do we have to issue an auto request? */
808 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100809 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530810 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000811 us->transport_reset(us);
812 return USB_STOR_TRANSPORT_ERROR;
813 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100814 if ((us->protocol == US_PR_CBI) &&
815 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
816 (srb->cmd[0] == SCSI_INQUIRY))) {
817 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530818 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000819 return USB_STOR_TRANSPORT_GOOD;
820 }
821 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100822 memset(&psrb->cmd[0], 0, 12);
823 psrb->cmd[0] = SCSI_REQ_SENSE;
824 psrb->cmd[1] = srb->lun << 5;
825 psrb->cmd[4] = 18;
826 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200827 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100828 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000829 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100830 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530831 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000832 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100833 if (us->protocol == US_PR_CBI)
834 status = usb_stor_CBI_get_status(psrb, us);
835
836 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530837 debug(" AUTO REQUEST ERROR %ld\n",
838 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000839 return USB_STOR_TRANSPORT_ERROR;
840 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530841 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
842 srb->sense_buf[0], srb->sense_buf[2],
843 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 if ((srb->sense_buf[2] == 0) &&
846 (srb->sense_buf[12] == 0) &&
847 (srb->sense_buf[13] == 0)) {
848 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000849 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 }
851
wdenkaffae2b2002-08-17 09:36:01 +0000852 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 switch (srb->sense_buf[2]) {
854 case 0x01:
855 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000856 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000857 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100858 case 0x02:
859 /* Not Ready */
860 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
861 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
862 " 0x%02X (NOT READY)\n", srb->cmd[0],
863 srb->sense_buf[0], srb->sense_buf[2],
864 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000865 return USB_STOR_TRANSPORT_FAILED;
866 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000867 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000868 goto do_retry;
869 }
870 break;
871 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100872 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
873 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
874 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
875 srb->sense_buf[2], srb->sense_buf[12],
876 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000877 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878 } else
wdenk149dded2003-09-10 18:20:28 +0000879 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000880 break;
wdenkaffae2b2002-08-17 09:36:01 +0000881 }
882 return USB_STOR_TRANSPORT_FAILED;
883}
884
885
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100886static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000887{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100888 int retry, i;
889 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000890 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100891 memset(&srb->cmd[0], 0, 12);
892 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200893 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100894 srb->cmd[4] = 36;
895 srb->datalen = 36;
896 srb->cmdlen = 12;
897 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530898 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100899 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000900 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200901 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000902
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100903 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000904 printf("error in inquiry\n");
905 return -1;
906 }
907 return 0;
908}
909
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100910static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000911{
912 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000913
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 ptr = (char *)srb->pdata;
915 memset(&srb->cmd[0], 0, 12);
916 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200917 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100918 srb->cmd[4] = 18;
919 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200920 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100921 srb->cmdlen = 12;
922 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530923 debug("Request Sense returned %02X %02X %02X\n",
924 srb->sense_buf[2], srb->sense_buf[12],
925 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100926 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000927 return 0;
928}
929
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100930static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000931{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200932 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000933
wdenkaffae2b2002-08-17 09:36:01 +0000934 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100935 memset(&srb->cmd[0], 0, 12);
936 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200937 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100938 srb->datalen = 0;
939 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200940 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
941 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000942 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200943 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100944 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800945 /*
946 * Check the Key Code Qualifier, if it matches
947 * "Not Ready - medium not present"
948 * (the sense Key equals 0x2 and the ASC is 0x3a)
949 * return immediately as the medium being absent won't change
950 * unless there is a user action.
951 */
952 if ((srb->sense_buf[2] == 0x02) &&
953 (srb->sense_buf[12] == 0x3a))
954 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000955 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100956 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000957
wdenkaffae2b2002-08-17 09:36:01 +0000958 return -1;
959}
960
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100961static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000962{
963 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100964 /* XXX retries */
965 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000966 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967 memset(&srb->cmd[0], 0, 12);
968 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200969 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100970 srb->datalen = 8;
971 srb->cmdlen = 12;
972 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000973 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100974 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000975
wdenkaffae2b2002-08-17 09:36:01 +0000976 return -1;
977}
978
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100979static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
980 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000981{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100982 memset(&srb->cmd[0], 0, 12);
983 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200984 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100985 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
986 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
987 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
988 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
989 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
990 srb->cmd[8] = (unsigned char) blocks & 0xff;
991 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530992 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100993 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000994}
995
Mahavir Jain127e1082009-11-03 12:22:10 +0530996static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
997 unsigned short blocks)
998{
999 memset(&srb->cmd[0], 0, 12);
1000 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001001 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301002 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1003 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1004 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1005 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1006 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1007 srb->cmd[8] = (unsigned char) blocks & 0xff;
1008 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301009 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301010 return ss->transport(srb, ss);
1011}
1012
wdenkaffae2b2002-08-17 09:36:01 +00001013
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001014#ifdef CONFIG_USB_BIN_FIXUP
1015/*
1016 * Some USB storage devices queried for SCSI identification data respond with
1017 * binary strings, which if output to the console freeze the terminal. The
1018 * workaround is to modify the vendor and product strings read from such
1019 * device with proper values (as reported by 'usb info').
1020 *
1021 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001022 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001023 */
1024static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1025 unsigned char vendor[],
1026 unsigned char product[]) {
1027 const unsigned char max_vendor_len = 40;
1028 const unsigned char max_product_len = 20;
1029 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001030 strncpy((char *)vendor, "SMSC", max_vendor_len);
1031 strncpy((char *)product, "Flash Media Cntrller",
1032 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001033 }
1034}
1035#endif /* CONFIG_USB_BIN_FIXUP */
1036
Simon Glass4101f682016-02-29 15:25:34 -07001037static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001038 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001039{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001040 lbaint_t start, blks;
1041 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001042 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001043 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001044 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001045 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001046 ccb *srb = &usb_ccb;
1047
1048 if (blkcnt == 0)
1049 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 /* Setup device */
Simon Glass9807c3b2016-02-29 15:25:54 -07001051 debug("\nusb_read: udev %d\n", block_dev->devnum);
1052 udev = usb_dev_desc[block_dev->devnum].priv;
1053 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001054 debug("%s: No device\n", __func__);
1055 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001056 }
Simon Glass9807c3b2016-02-29 15:25:54 -07001057 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001058
1059 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass9807c3b2016-02-29 15:25:54 -07001060 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001061 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001062 start = blknr;
1063 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064
Simon Glass9807c3b2016-02-29 15:25:54 -07001065 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1066 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001067
wdenkaffae2b2002-08-17 09:36:01 +00001068 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 /* XXX need some comment here */
1070 retry = 2;
1071 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001072 if (blks > USB_MAX_XFER_BLK)
1073 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001074 else
1075 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001076retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001077 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001078 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001079 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001080 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001081 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301082 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001083 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001084 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001085 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001086 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001087 break;
1088 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001089 start += smallblks;
1090 blks -= smallblks;
1091 buf_addr += srb->datalen;
1092 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001093 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001094
Vivek Gautamceb49722013-04-12 16:34:33 +05301095 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001096 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301097 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001098
wdenkaffae2b2002-08-17 09:36:01 +00001099 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001100 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001101 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001102 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001103}
1104
Simon Glass4101f682016-02-29 15:25:34 -07001105static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001106 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301107{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001108 lbaint_t start, blks;
1109 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301110 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001111 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001112 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001113 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301114 ccb *srb = &usb_ccb;
1115
1116 if (blkcnt == 0)
1117 return 0;
1118
Mahavir Jain127e1082009-11-03 12:22:10 +05301119 /* Setup device */
Simon Glass9807c3b2016-02-29 15:25:54 -07001120 debug("\nusb_read: udev %d\n", block_dev->devnum);
1121 udev = usb_dev_desc[block_dev->devnum].priv;
1122 if (!udev) {
1123 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001124 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001125 }
1126 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301127
1128 usb_disable_asynch(1); /* asynch transfer not allowed */
1129
Simon Glass9807c3b2016-02-29 15:25:54 -07001130 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001131 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301132 start = blknr;
1133 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301134
Simon Glass9807c3b2016-02-29 15:25:54 -07001135 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1136 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301137
1138 do {
1139 /* If write fails retry for max retry count else
1140 * return with number of blocks written successfully.
1141 */
1142 retry = 2;
1143 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001144 if (blks > USB_MAX_XFER_BLK)
1145 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301146 else
1147 smallblks = (unsigned short) blks;
1148retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001149 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301150 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001151 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301152 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001153 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301154 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001155 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301156 if (retry--)
1157 goto retry_it;
1158 blkcnt -= blks;
1159 break;
1160 }
1161 start += smallblks;
1162 blks -= smallblks;
1163 buf_addr += srb->datalen;
1164 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001165 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301166
Simon Glass4fd074d2014-10-15 04:38:38 -06001167 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1168 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301169
1170 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001171 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001172 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301173 return blkcnt;
1174
1175}
wdenkaffae2b2002-08-17 09:36:01 +00001176
1177/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001178int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1179 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001180{
Tom Rix8f8bd562009-10-31 12:37:38 -05001181 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001182 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301183 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001184 unsigned int flags = 0;
1185
wdenkaffae2b2002-08-17 09:36:01 +00001186 /* let's examine the device now */
1187 iface = &dev->config.if_desc[ifnum];
1188
wdenkaffae2b2002-08-17 09:36:01 +00001189 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001190 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1191 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1192 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001193 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001194 /* if it's not a mass storage, we go no further */
1195 return 0;
1196 }
1197
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001198 memset(ss, 0, sizeof(struct us_data));
1199
wdenkaffae2b2002-08-17 09:36:01 +00001200 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301201 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001202
1203 /* Initialize the us_data structure with some useful info */
1204 ss->flags = flags;
1205 ss->ifnum = ifnum;
1206 ss->pusb_dev = dev;
1207 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001208 ss->subclass = iface->desc.bInterfaceSubClass;
1209 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001210
1211 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301212 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001213 switch (ss->protocol) {
1214 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301215 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001216 ss->transport = usb_stor_CB_transport;
1217 ss->transport_reset = usb_stor_CB_reset;
1218 break;
1219
1220 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301221 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001222 ss->transport = usb_stor_CB_transport;
1223 ss->transport_reset = usb_stor_CB_reset;
1224 break;
wdenk149dded2003-09-10 18:20:28 +00001225 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301226 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001227 ss->transport = usb_stor_BBB_transport;
1228 ss->transport_reset = usb_stor_BBB_reset;
1229 break;
wdenkaffae2b2002-08-17 09:36:01 +00001230 default:
wdenk80885a92004-02-26 23:46:20 +00001231 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001232 return 0;
1233 break;
1234 }
1235
1236 /*
1237 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1238 * An optional interrupt is OK (necessary for CBI protocol).
1239 * We will ignore any others.
1240 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001241 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301242 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001243 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301244 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001245 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301246 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1247 ss->ep_in = ep_desc->bEndpointAddress &
1248 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001249 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001250 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301251 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001252 USB_ENDPOINT_NUMBER_MASK;
1253 }
1254
1255 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301256 if ((ep_desc->bmAttributes &
1257 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1258 ss->ep_int = ep_desc->bEndpointAddress &
1259 USB_ENDPOINT_NUMBER_MASK;
1260 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001261 }
1262 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301263 debug("Endpoints In %d Out %d Int %d\n",
1264 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001265
1266 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001267 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001268 !ss->ep_in || !ss->ep_out ||
1269 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301270 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001271 return 0;
1272 }
1273 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001274 /* We only handle certain protocols. Currently, these are
1275 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001276 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001277 */
wdenk80885a92004-02-26 23:46:20 +00001278 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1279 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001280 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001281 return 0;
1282 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001283 if (ss->ep_int) {
1284 /* we had found an interrupt endpoint, prepare irq pipe
1285 * set up the IRQ pipe and handler
1286 */
wdenkaffae2b2002-08-17 09:36:01 +00001287 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1288 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1289 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001290 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001291 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001292 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001293 return 1;
1294}
1295
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001296int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001297 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001298{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001299 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001300 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1301 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1302 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001303 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001304
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001305 pccb->pdata = usb_stor_buf;
1306
1307 dev_desc->target = dev->devnum;
1308 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301309 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001310
Simon Glass1d5827a2015-03-25 12:22:12 -06001311 if (usb_inquiry(pccb, ss)) {
1312 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001313 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001314 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001315
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001316 perq = usb_stor_buf[0];
1317 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001318
Soeren Moch6a559bb2014-11-08 07:02:14 +01001319 /*
1320 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1321 * they would not respond to test_unit_ready .
1322 */
1323 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001324 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001325 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001326 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001327 if ((modi&0x80) == 0x80) {
1328 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001329 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001330 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001331 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1332 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1333 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001334 dev_desc->vendor[8] = 0;
1335 dev_desc->product[16] = 0;
1336 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001337#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001338 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1339 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001340#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301341 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1342 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001343 if (usb_test_unit_ready(pccb, ss)) {
1344 printf("Device NOT ready\n"
1345 " Request Sense returned %02X %02X %02X\n",
1346 pccb->sense_buf[2], pccb->sense_buf[12],
1347 pccb->sense_buf[13]);
1348 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001349 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001350 return 1;
1351 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001352 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001353 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001354 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001355 memset(pccb->pdata, 0, 8);
1356 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001357 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001358 cap[0] = 2880;
1359 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001360 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001361 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001362 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001363#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001364 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1365 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001366
Christian Eggersc9182612008-05-21 22:12:00 +02001367 cap[0] = cpu_to_be32(cap[0]);
1368 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001369#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001370
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001371 capacity = be32_to_cpu(cap[0]) + 1;
1372 blksz = be32_to_cpu(cap[1]);
1373
1374 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1375 dev_desc->lba = capacity;
1376 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001377 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001378 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301379 debug(" address %d\n", dev_desc->target);
1380 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001381
Simon Glass3e8bd462016-02-29 15:25:48 -07001382 part_init(dev_desc);
wdenkaffae2b2002-08-17 09:36:01 +00001383
Vivek Gautamceb49722013-04-12 16:34:33 +05301384 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001385 return 1;
1386}
Simon Glassacf277a2015-03-25 12:22:16 -06001387
1388#ifdef CONFIG_DM_USB
1389
1390static int usb_mass_storage_probe(struct udevice *dev)
1391{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001392 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001393 int ret;
1394
1395 usb_disable_asynch(1); /* asynch transfer not allowed */
1396 ret = usb_stor_probe_device(udev);
1397 usb_disable_asynch(0); /* asynch transfer allowed */
1398
1399 return ret;
1400}
1401
1402static const struct udevice_id usb_mass_storage_ids[] = {
1403 { .compatible = "usb-mass-storage" },
1404 { }
1405};
1406
1407U_BOOT_DRIVER(usb_mass_storage) = {
1408 .name = "usb_mass_storage",
1409 .id = UCLASS_MASS_STORAGE,
1410 .of_match = usb_mass_storage_ids,
1411 .probe = usb_mass_storage_probe,
1412};
1413
1414UCLASS_DRIVER(usb_mass_storage) = {
1415 .id = UCLASS_MASS_STORAGE,
1416 .name = "usb_mass_storage",
1417};
1418
1419static const struct usb_device_id mass_storage_id_table[] = {
1420 {
1421 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1422 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1423 },
1424 { } /* Terminating entry */
1425};
1426
Simon Glassabb59cf2015-07-06 16:47:51 -06001427U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glassacf277a2015-03-25 12:22:16 -06001428
1429#endif