blob: 14728242f01cdf0c7e373a86cd3b90e628b431cd [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>
Simon Glass07b2b782016-02-29 15:25:58 -070046#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000047
Grant Likely735dd972007-02-20 09:04:34 +010048#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000049#include <usb.h>
50
wdenk80885a92004-02-26 23:46:20 +000051#undef BBB_COMDAT_TRACE
52#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000053
wdenkaffae2b2002-08-17 09:36:01 +000054#include <scsi.h>
55/* direction table -- this indicates the direction of the data
56 * transfer for each command code -- a 1 indicates input
57 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040058static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000059 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
60 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
63};
64#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
65
Puneet Saxenaf5766132012-04-03 14:56:06 +053066static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010067static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000068
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
Simon Glass07b2b782016-02-29 15:25:58 -070071#ifndef CONFIG_BLK
Simon Glass4101f682016-02-29 15:25:34 -070072static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -070073#endif
wdenkaffae2b2002-08-17 09:36:01 +000074
75struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010076typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
77typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000078
79struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010080 struct usb_device *pusb_dev; /* this usb_device */
81
82 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020083# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010084 unsigned char ifnum; /* interface number */
85 unsigned char ep_in; /* in endpoint */
86 unsigned char ep_out; /* out ....... */
87 unsigned char ep_int; /* interrupt . */
88 unsigned char subclass; /* as in overview */
89 unsigned char protocol; /* .............. */
90 unsigned char attention_done; /* force attn on first cmd */
91 unsigned short ip_data; /* interrupt data */
92 int action; /* what to do */
93 int ip_wanted; /* needed */
94 int *irq_handle; /* for USB int requests */
95 unsigned int irqpipe; /* pipe for release_irq */
96 unsigned char irqmaxp; /* max packed for irq Pipe */
97 unsigned char irqinterval; /* Intervall for IRQ Pipe */
98 ccb *srb; /* current srb */
99 trans_reset transport_reset; /* reset routine */
100 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000101};
102
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200103#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000104/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200105 * The U-Boot EHCI driver can handle any transfer length as long as there is
106 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
107 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000108 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200109#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200110#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200111#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200112#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000113
Simon Glass07b2b782016-02-29 15:25:58 -0700114#ifndef CONFIG_BLK
wdenkaffae2b2002-08-17 09:36:01 +0000115static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -0700116#endif
wdenkaffae2b2002-08-17 09:36:01 +0000117
wdenk80885a92004-02-26 23:46:20 +0000118#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000119#define USB_STOR_TRANSPORT_FAILED -1
120#define USB_STOR_TRANSPORT_ERROR -2
121
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100122int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glass4101f682016-02-29 15:25:34 -0700123 struct blk_desc *dev_desc);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100124int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
125 struct us_data *ss);
Simon Glass07b2b782016-02-29 15:25:58 -0700126#ifdef CONFIG_BLK
127static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
128 lbaint_t blkcnt, void *buffer);
129static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
130 lbaint_t blkcnt, const void *buffer);
131#else
Simon Glass4101f682016-02-29 15:25:34 -0700132static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700133 lbaint_t blkcnt, void *buffer);
Simon Glass4101f682016-02-29 15:25:34 -0700134static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700135 lbaint_t blkcnt, const void *buffer);
Simon Glass07b2b782016-02-29 15:25:58 -0700136#endif
wdenkaffae2b2002-08-17 09:36:01 +0000137void uhci_show_temp_int_td(void);
138
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000139#ifdef CONFIG_PARTITIONS
Simon Glass4101f682016-02-29 15:25:34 -0700140struct blk_desc *usb_stor_get_dev(int index)
wdenkaffae2b2002-08-17 09:36:01 +0000141{
Simon Glass07b2b782016-02-29 15:25:58 -0700142#ifdef CONFIG_BLK
143 struct udevice *dev;
144 int ret;
145
146 ret = blk_get_device(IF_TYPE_USB, index, &dev);
147 if (ret)
148 return NULL;
149 return dev_get_uclass_platdata(dev);
150#else
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200151 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
Simon Glass07b2b782016-02-29 15:25:58 -0700152#endif
wdenkaffae2b2002-08-17 09:36:01 +0000153}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000154#endif
wdenkaffae2b2002-08-17 09:36:01 +0000155
Kim Phillips199adb62012-10-29 13:34:32 +0000156static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000157{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200158 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000159}
160
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100161/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200162 * show info on storage devices; 'usb start/init' must be invoked earlier
163 * as we only retrieve structures populated during devices initialization
164 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100165int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200166{
Simon Glass9807c3b2016-02-29 15:25:54 -0700167 int count = 0;
Simon Glass07b2b782016-02-29 15:25:58 -0700168#ifdef CONFIG_BLK
169 struct udevice *dev;
170
171 for (blk_first_device(IF_TYPE_USB, &dev);
172 dev;
173 blk_next_device(&dev)) {
174 struct blk_desc *desc = dev_get_uclass_platdata(dev);
175
176 printf(" Device %d: ", desc->devnum);
177 dev_print(desc);
178 count++;
179 }
180#else
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200181 int i;
182
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100183 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200184 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100185 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200186 dev_print(&usb_dev_desc[i]);
187 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100188 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100189 }
Simon Glass07b2b782016-02-29 15:25:58 -0700190#endif
Simon Glass9807c3b2016-02-29 15:25:54 -0700191 if (!count) {
192 printf("No storage devices, perhaps not 'usb start'ed..?\n");
193 return 1;
194 }
195
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100196 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200197}
198
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200199static unsigned int usb_get_max_lun(struct us_data *us)
200{
201 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530202 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200203 len = usb_control_msg(us->pusb_dev,
204 usb_rcvctrlpipe(us->pusb_dev, 0),
205 US_BBB_GET_MAX_LUN,
206 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
207 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530208 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200209 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530210 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530211 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200212}
213
Simon Glass9807c3b2016-02-29 15:25:54 -0700214static int usb_stor_probe_device(struct usb_device *udev)
Simon Glass91557572015-03-25 12:22:15 -0600215{
Simon Glass9807c3b2016-02-29 15:25:54 -0700216 int lun, max_lun;
Simon Glass07b2b782016-02-29 15:25:58 -0700217
218#ifdef CONFIG_BLK
219 struct us_data *data;
220 char dev_name[30], *str;
221 int ret;
222#else
Simon Glass9807c3b2016-02-29 15:25:54 -0700223 int start;
224
225 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600226 return -ENOENT; /* no more devices available */
Simon Glass07b2b782016-02-29 15:25:58 -0700227#endif
Simon Glass91557572015-03-25 12:22:15 -0600228
Simon Glass07b2b782016-02-29 15:25:58 -0700229 debug("\n\nProbing for storage\n");
230#ifdef CONFIG_BLK
231 /*
232 * We store the us_data in the mass storage device's platdata. It
233 * is shared by all LUNs (block devices) attached to this mass storage
234 * device.
235 */
236 data = dev_get_platdata(udev->dev);
237 if (!usb_storage_probe(udev, 0, data))
238 return 0;
239 max_lun = usb_get_max_lun(data);
240 for (lun = 0; lun <= max_lun; lun++) {
241 struct blk_desc *blkdev;
242 struct udevice *dev;
243
244 snprintf(dev_name, sizeof(dev_name), "%s.lun%d",
245 udev->dev->name, lun);
246 str = strdup(dev_name);
247 if (!str)
248 return -ENOMEM;
249 ret = blk_create_device(udev->dev, "usb_storage_blk", str,
250 IF_TYPE_USB, usb_max_devs, 512, 0, &dev);
251 if (ret) {
252 debug("Cannot bind driver\n");
253 return ret;
254 }
255
256 blkdev = dev_get_uclass_platdata(dev);
257 blkdev->target = 0xff;
258 blkdev->lun = lun;
259
260 ret = usb_stor_get_info(udev, data, blkdev);
261 if (ret == 1)
262 ret = blk_prepare_device(dev);
263 if (!ret) {
264 usb_max_devs++;
265 debug("%s: Found device %p\n", __func__, udev);
266 } else {
267 debug("usb_stor_get_info: Invalid device\n");
268 ret = device_unbind(dev);
269 if (ret)
270 return ret;
271 }
272 }
273#else
Simon Glassc89e79d2016-02-29 15:25:53 -0700274 /* We don't have space to even probe if we hit the maximum */
275 if (usb_max_devs == USB_MAX_STOR_DEV) {
276 printf("max USB Storage Device reached: %d stopping\n",
277 usb_max_devs);
278 return -ENOSPC;
279 }
280
Simon Glass9807c3b2016-02-29 15:25:54 -0700281 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
282 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600283
Simon Glass9807c3b2016-02-29 15:25:54 -0700284 /*
285 * OK, it's a storage device. Iterate over its LUNs and populate
286 * usb_dev_desc'
287 */
288 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600289
Simon Glass9807c3b2016-02-29 15:25:54 -0700290 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
291 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
292 lun++) {
293 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600294
Simon Glass9807c3b2016-02-29 15:25:54 -0700295 blkdev = &usb_dev_desc[usb_max_devs];
296 memset(blkdev, '\0', sizeof(struct blk_desc));
297 blkdev->if_type = IF_TYPE_USB;
298 blkdev->devnum = usb_max_devs;
299 blkdev->part_type = PART_TYPE_UNKNOWN;
300 blkdev->target = 0xff;
301 blkdev->type = DEV_TYPE_UNKNOWN;
302 blkdev->block_read = usb_stor_read;
303 blkdev->block_write = usb_stor_write;
304 blkdev->lun = lun;
305 blkdev->priv = udev;
306
307 if (usb_stor_get_info(udev, &usb_stor[start],
308 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700309 debug("partype: %d\n", blkdev->part_type);
310 part_init(blkdev);
311 debug("partype: %d\n", blkdev->part_type);
Simon Glass9807c3b2016-02-29 15:25:54 -0700312 usb_max_devs++;
313 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600314 }
315 }
Simon Glass07b2b782016-02-29 15:25:58 -0700316#endif
Simon Glass91557572015-03-25 12:22:15 -0600317
Simon Glass91557572015-03-25 12:22:15 -0600318 return 0;
319}
320
321void usb_stor_reset(void)
322{
323 usb_max_devs = 0;
324}
325
Simon Glassacf277a2015-03-25 12:22:16 -0600326#ifndef CONFIG_DM_USB
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100327/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200328 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000329 * to the user if mode = 1
330 * returns current device or -1 if no
331 */
332int usb_stor_scan(int mode)
333{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600334 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000335
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100336 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200337 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100338
wdenkaffae2b2002-08-17 09:36:01 +0000339 usb_disable_asynch(1); /* asynch transfer not allowed */
340
Simon Glass91557572015-03-25 12:22:15 -0600341 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100342 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600343 struct usb_device *dev;
344
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100345 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530346 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600347 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000348 break;
wdenkaffae2b2002-08-17 09:36:01 +0000349 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200350
wdenkaffae2b2002-08-17 09:36:01 +0000351 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200352 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100353 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000354 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100355 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000356}
Simon Glassacf277a2015-03-25 12:22:16 -0600357#endif
wdenkaffae2b2002-08-17 09:36:01 +0000358
359static int usb_stor_irq(struct usb_device *dev)
360{
361 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100362 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000363
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100364 if (us->ip_wanted)
365 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000366 return 0;
367}
368
369
Vivek Gautamceb49722013-04-12 16:34:33 +0530370#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000371
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100372static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000373{
374 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100375 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
376 for (i = 0; i < 12; i++)
377 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000378 printf("\n");
379}
380
381static void display_int_status(unsigned long tmp)
382{
383 printf("Status: %s %s %s %s %s %s %s\n",
384 (tmp & USB_ST_ACTIVE) ? "Active" : "",
385 (tmp & USB_ST_STALLED) ? "Stalled" : "",
386 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
387 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
388 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
389 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
390 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
391}
392#endif
393/***********************************************************************
394 * Data transfer routines
395 ***********************************************************************/
396
397static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
398{
399 int max_size;
400 int this_xfer;
401 int result;
402 int partial;
403 int maxtry;
404 int stat;
405
406 /* determine the maximum packet size for these transfers */
407 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
408
409 /* while we have data left to transfer */
410 while (length) {
411
412 /* calculate how long this will be -- maximum or a remainder */
413 this_xfer = length > max_size ? max_size : length;
414 length -= this_xfer;
415
416 /* setup the retry counter */
417 maxtry = 10;
418
419 /* set up the transfer loop */
420 do {
421 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600422 debug("Bulk xfer 0x%lx(%d) try #%d\n",
423 (ulong)map_to_sysmem(buf), this_xfer,
424 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000425 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100426 this_xfer, &partial,
427 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530428 debug("bulk_msg returned %d xferred %d/%d\n",
429 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100430 if (us->pusb_dev->status != 0) {
431 /* if we stall, we need to clear it before
432 * we go on
433 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530434#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000435 display_int_status(us->pusb_dev->status);
436#endif
437 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530438 debug("stalled ->clearing endpoint" \
439 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000440 stat = us->pusb_dev->status;
441 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100442 us->pusb_dev->status = stat;
443 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530444 debug("bulk transferred" \
445 "with error %lX," \
446 " but data ok\n",
447 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000448 return 0;
449 }
450 else
451 return result;
452 }
453 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530454 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000455 return result;
456 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530457 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100458 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530459 debug(" %ld, but data ok\n",
460 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000461 return 0;
462 }
463 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530464 debug(" %ld, data %d\n",
465 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000466 if (!maxtry--)
467 return result;
468 }
469 /* update to show what data was transferred */
470 this_xfer -= partial;
471 buf += partial;
472 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100473 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000474 }
475
476 /* if we get here, we're done and successful */
477 return 0;
478}
479
wdenk149dded2003-09-10 18:20:28 +0000480static int usb_stor_BBB_reset(struct us_data *us)
481{
482 int result;
483 unsigned int pipe;
484
485 /*
486 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
487 *
488 * For Reset Recovery the host shall issue in the following order:
489 * a) a Bulk-Only Mass Storage Reset
490 * b) a Clear Feature HALT to the Bulk-In endpoint
491 * c) a Clear Feature HALT to the Bulk-Out endpoint
492 *
493 * This is done in 3 steps.
494 *
495 * If the reset doesn't succeed, the device should be port reset.
496 *
497 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
498 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530499 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100500 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
501 US_BBB_RESET,
502 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000503 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200504
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100505 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530506 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000507 return -1;
508 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200509
wdenk149dded2003-09-10 18:20:28 +0000510 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000511 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530512 debug("BBB_reset result %d: status %lX reset\n",
513 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000514 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
515 result = usb_clear_halt(us->pusb_dev, pipe);
516 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000517 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530518 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
519 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000520 /* long wait for reset */
521 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
522 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000523 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530524 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
525 result, us->pusb_dev->status);
526 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000527 return 0;
528}
529
wdenkaffae2b2002-08-17 09:36:01 +0000530/* FIXME: this reset function doesn't really reset the port, and it
531 * should. Actually it should probably do what it's doing here, and
532 * reset the port physically
533 */
534static int usb_stor_CB_reset(struct us_data *us)
535{
536 unsigned char cmd[12];
537 int result;
538
Vivek Gautamceb49722013-04-12 16:34:33 +0530539 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100540 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000541 cmd[0] = SCSI_SEND_DIAG;
542 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100543 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
544 US_CBI_ADSC,
545 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
546 0, us->ifnum, cmd, sizeof(cmd),
547 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000548
549 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000550 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530551 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
552 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000553 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
554 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
555
Vivek Gautamceb49722013-04-12 16:34:33 +0530556 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000557 return 0;
558}
559
wdenk149dded2003-09-10 18:20:28 +0000560/*
561 * Set up the command for a BBB device. Note that the actual SCSI
562 * command is copied into cbw.CBWCDB.
563 */
Kim Phillips199adb62012-10-29 13:34:32 +0000564static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000565{
566 int result;
567 int actlen;
568 int dir_in;
569 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600570 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000571
572 dir_in = US_DIRECTION(srb->cmd[0]);
573
574#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530575 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100576 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
577 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000578 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100579 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000580 printf("cmd[%d] %#x ", result, srb->cmd[result]);
581 printf("\n");
582 }
583#endif
584 /* sanity checks */
585 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530586 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000587 return -1;
588 }
589
590 /* always OUT to the ep */
591 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
592
Puneet Saxenaf5766132012-04-03 14:56:06 +0530593 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
594 cbw->dCBWTag = cpu_to_le32(CBWTag++);
595 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
596 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
597 cbw->bCBWLUN = srb->lun;
598 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000599 /* copy the command data into the CBW command data buffer */
600 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300601
Puneet Saxenaf5766132012-04-03 14:56:06 +0530602 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
603 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100604 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000605 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530606 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000607 return result;
608}
609
wdenkaffae2b2002-08-17 09:36:01 +0000610/* FIXME: we also need a CBI_command which sets up the completion
611 * interrupt, and waits for it
612 */
Kim Phillips199adb62012-10-29 13:34:32 +0000613static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000614{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200615 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100616 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000617 unsigned int pipe;
618 unsigned long status;
619
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100620 retry = 5;
621 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000622
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100623 if (dir_in)
624 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
625 else
626 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
627
628 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530629 debug("CBI gets a command: Try %d\n", 5 - retry);
630#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000631 usb_show_srb(srb);
632#endif
633 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100634 result = usb_control_msg(us->pusb_dev,
635 usb_sndctrlpipe(us->pusb_dev , 0),
636 US_CBI_ADSC,
637 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000638 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100639 srb->cmd, srb->cmdlen,
640 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530641 debug("CB_transport: control msg returned %d, status %lX\n",
642 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000643 /* check the return code for the command */
644 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100645 if (us->pusb_dev->status & USB_ST_STALLED) {
646 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530647 debug(" stall during command found," \
648 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100649 usb_clear_halt(us->pusb_dev,
650 usb_sndctrlpipe(us->pusb_dev, 0));
651 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000652 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530653 debug(" error during command %02X" \
654 " Stat = %lX\n", srb->cmd[0],
655 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000656 return result;
657 }
658 /* transfer the data payload for this command, if one exists*/
659
Vivek Gautamceb49722013-04-12 16:34:33 +0530660 debug("CB_transport: control msg returned %d," \
661 " direction is %s to go 0x%lx\n", result,
662 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000663 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 result = us_one_transfer(us, pipe, (char *)srb->pdata,
665 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530666 debug("CBI attempted to transfer data," \
667 " result is %d status %lX, len %d\n",
668 result, us->pusb_dev->status,
669 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100670 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000671 break;
672 } /* if (srb->datalen) */
673 else
674 break;
675 }
676 /* return result */
677
678 return result;
679}
680
681
Kim Phillips199adb62012-10-29 13:34:32 +0000682static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000683{
684 int timeout;
685
wdenk80885a92004-02-26 23:46:20 +0000686 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100687 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000688 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
689 timeout = 1000;
690 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300691 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000692 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000693 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000694 }
695 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100696 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000697 us->ip_wanted = 0;
698 return USB_STOR_TRANSPORT_ERROR;
699 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530700 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
701 us->ip_data, us->pusb_dev->irq_act_len,
702 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000703 /* UFI gives us ASC and ASCQ, like a request sense */
704 if (us->subclass == US_SC_UFI) {
705 if (srb->cmd[0] == SCSI_REQ_SENSE ||
706 srb->cmd[0] == SCSI_INQUIRY)
707 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000708 else if (us->ip_data)
709 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000710 else
wdenk80885a92004-02-26 23:46:20 +0000711 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000712 }
713 /* otherwise, we interpret the data normally */
714 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000715 case 0x0001:
716 return USB_STOR_TRANSPORT_GOOD;
717 case 0x0002:
718 return USB_STOR_TRANSPORT_FAILED;
719 default:
720 return USB_STOR_TRANSPORT_ERROR;
721 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000722 return USB_STOR_TRANSPORT_ERROR;
723}
724
725#define USB_TRANSPORT_UNKNOWN_RETRY 5
726#define USB_TRANSPORT_NOT_READY_RETRY 10
727
wdenk149dded2003-09-10 18:20:28 +0000728/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000729static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000730{
731 int result;
732
733 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100734 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000735 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000736 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000737 return result;
738}
739
Kim Phillips199adb62012-10-29 13:34:32 +0000740static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000741{
742 int result, retry;
743 int dir_in;
744 int actlen, data_actlen;
745 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600746 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000747#ifdef BBB_XPORT_TRACE
748 unsigned char *ptr;
749 int index;
750#endif
751
752 dir_in = US_DIRECTION(srb->cmd[0]);
753
754 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530755 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000756 result = usb_stor_BBB_comdat(srb, us);
757 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530758 debug("failed to send CBW status %ld\n",
759 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000760 usb_stor_BBB_reset(us);
761 return USB_STOR_TRANSPORT_FAILED;
762 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200763 if (!(us->flags & USB_READY))
764 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000765 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
766 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
767 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000768 data_actlen = 0;
769 /* no data, go immediately to the STATUS phase */
770 if (srb->datalen == 0)
771 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530772 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000773 if (dir_in)
774 pipe = pipein;
775 else
776 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300777
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100778 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
779 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000780 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100781 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530782 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000783 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100784 result = usb_stor_BBB_clear_endpt_stall(us,
785 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000786 if (result >= 0)
787 /* continue on to STATUS phase */
788 goto st;
789 }
790 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530791 debug("usb_bulk_msg error status %ld\n",
792 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000793 usb_stor_BBB_reset(us);
794 return USB_STOR_TRANSPORT_FAILED;
795 }
796#ifdef BBB_XPORT_TRACE
797 for (index = 0; index < data_actlen; index++)
798 printf("pdata[%d] %#x ", index, srb->pdata[index]);
799 printf("\n");
800#endif
801 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100802st:
wdenk149dded2003-09-10 18:20:28 +0000803 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100804again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530805 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530806 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200807 &actlen, USB_CNTL_TIMEOUT*5);
808
wdenk149dded2003-09-10 18:20:28 +0000809 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100810 if ((result < 0) && (retry < 1) &&
811 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530812 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000813 /* clear the STALL on the endpoint */
814 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
815 if (result >= 0 && (retry++ < 1))
816 /* do a retry */
817 goto again;
818 }
819 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530820 debug("usb_bulk_msg error status %ld\n",
821 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000822 usb_stor_BBB_reset(us);
823 return USB_STOR_TRANSPORT_FAILED;
824 }
825#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530826 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000827 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
828 printf("ptr[%d] %#x ", index, ptr[index]);
829 printf("\n");
830#endif
831 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530832 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000833 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
834 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530835 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530836 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000837 usb_stor_BBB_reset(us);
838 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530839 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530840 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000841 usb_stor_BBB_reset(us);
842 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530843 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530844 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000845 usb_stor_BBB_reset(us);
846 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530847 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530848 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000849 usb_stor_BBB_reset(us);
850 return USB_STOR_TRANSPORT_FAILED;
851 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530852 debug("transferred %dB instead of %ldB\n",
853 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000854 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530855 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530856 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000857 return USB_STOR_TRANSPORT_FAILED;
858 }
859
860 return result;
861}
862
Kim Phillips199adb62012-10-29 13:34:32 +0000863static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000864{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100865 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000866 ccb *psrb;
867 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100868 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000869
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200870 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100871 status = USB_STOR_TRANSPORT_GOOD;
872 retry = 0;
873 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000874 /* issue the command */
875do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100876 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530877 debug("command / Data returned %d, status %lX\n",
878 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000879 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100880 if (us->protocol == US_PR_CBI) {
881 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000882 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100883 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530884 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000885 return status;
886 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100887 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
888 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
889 if (!us->ip_data) {
890 /* if the status is good, report it */
891 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530892 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000893 return status;
894 }
895 }
896 }
897 /* do we have to issue an auto request? */
898 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100899 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530900 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000901 us->transport_reset(us);
902 return USB_STOR_TRANSPORT_ERROR;
903 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100904 if ((us->protocol == US_PR_CBI) &&
905 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
906 (srb->cmd[0] == SCSI_INQUIRY))) {
907 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530908 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000909 return USB_STOR_TRANSPORT_GOOD;
910 }
911 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100912 memset(&psrb->cmd[0], 0, 12);
913 psrb->cmd[0] = SCSI_REQ_SENSE;
914 psrb->cmd[1] = srb->lun << 5;
915 psrb->cmd[4] = 18;
916 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200917 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100918 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000919 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100920 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530921 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000922 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923 if (us->protocol == US_PR_CBI)
924 status = usb_stor_CBI_get_status(psrb, us);
925
926 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530927 debug(" AUTO REQUEST ERROR %ld\n",
928 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000929 return USB_STOR_TRANSPORT_ERROR;
930 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530931 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
932 srb->sense_buf[0], srb->sense_buf[2],
933 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000934 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100935 if ((srb->sense_buf[2] == 0) &&
936 (srb->sense_buf[12] == 0) &&
937 (srb->sense_buf[13] == 0)) {
938 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000939 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100940 }
941
wdenkaffae2b2002-08-17 09:36:01 +0000942 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100943 switch (srb->sense_buf[2]) {
944 case 0x01:
945 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000946 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000947 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100948 case 0x02:
949 /* Not Ready */
950 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
951 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
952 " 0x%02X (NOT READY)\n", srb->cmd[0],
953 srb->sense_buf[0], srb->sense_buf[2],
954 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000955 return USB_STOR_TRANSPORT_FAILED;
956 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000957 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000958 goto do_retry;
959 }
960 break;
961 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100962 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
963 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
964 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
965 srb->sense_buf[2], srb->sense_buf[12],
966 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000967 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100968 } else
wdenk149dded2003-09-10 18:20:28 +0000969 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000970 break;
wdenkaffae2b2002-08-17 09:36:01 +0000971 }
972 return USB_STOR_TRANSPORT_FAILED;
973}
974
975
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000977{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100978 int retry, i;
979 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000980 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100981 memset(&srb->cmd[0], 0, 12);
982 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200983 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100984 srb->cmd[4] = 36;
985 srb->datalen = 36;
986 srb->cmdlen = 12;
987 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530988 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100989 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000990 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200991 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000992
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100993 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000994 printf("error in inquiry\n");
995 return -1;
996 }
997 return 0;
998}
999
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001000static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001001{
1002 char *ptr;
wdenk80885a92004-02-26 23:46:20 +00001003
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001004 ptr = (char *)srb->pdata;
1005 memset(&srb->cmd[0], 0, 12);
1006 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001007 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001008 srb->cmd[4] = 18;
1009 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +02001010 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001011 srb->cmdlen = 12;
1012 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +05301013 debug("Request Sense returned %02X %02X %02X\n",
1014 srb->sense_buf[2], srb->sense_buf[12],
1015 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001016 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001017 return 0;
1018}
1019
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001020static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001021{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001022 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001023
wdenkaffae2b2002-08-17 09:36:01 +00001024 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001025 memset(&srb->cmd[0], 0, 12);
1026 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001027 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001028 srb->datalen = 0;
1029 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001030 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1031 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001032 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001033 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001034 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -08001035 /*
1036 * Check the Key Code Qualifier, if it matches
1037 * "Not Ready - medium not present"
1038 * (the sense Key equals 0x2 and the ASC is 0x3a)
1039 * return immediately as the medium being absent won't change
1040 * unless there is a user action.
1041 */
1042 if ((srb->sense_buf[2] == 0x02) &&
1043 (srb->sense_buf[12] == 0x3a))
1044 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +00001045 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001046 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001047
wdenkaffae2b2002-08-17 09:36:01 +00001048 return -1;
1049}
1050
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001051static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001052{
1053 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001054 /* XXX retries */
1055 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001056 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057 memset(&srb->cmd[0], 0, 12);
1058 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001059 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001060 srb->datalen = 8;
1061 srb->cmdlen = 12;
1062 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001063 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001065
wdenkaffae2b2002-08-17 09:36:01 +00001066 return -1;
1067}
1068
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
1070 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001071{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001072 memset(&srb->cmd[0], 0, 12);
1073 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001074 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001075 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1076 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1077 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1078 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1079 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1080 srb->cmd[8] = (unsigned char) blocks & 0xff;
1081 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301082 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001083 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001084}
1085
Mahavir Jain127e1082009-11-03 12:22:10 +05301086static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1087 unsigned short blocks)
1088{
1089 memset(&srb->cmd[0], 0, 12);
1090 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001091 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301092 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1093 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1094 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1095 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1096 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1097 srb->cmd[8] = (unsigned char) blocks & 0xff;
1098 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301099 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301100 return ss->transport(srb, ss);
1101}
1102
wdenkaffae2b2002-08-17 09:36:01 +00001103
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001104#ifdef CONFIG_USB_BIN_FIXUP
1105/*
1106 * Some USB storage devices queried for SCSI identification data respond with
1107 * binary strings, which if output to the console freeze the terminal. The
1108 * workaround is to modify the vendor and product strings read from such
1109 * device with proper values (as reported by 'usb info').
1110 *
1111 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001112 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001113 */
1114static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1115 unsigned char vendor[],
1116 unsigned char product[]) {
1117 const unsigned char max_vendor_len = 40;
1118 const unsigned char max_product_len = 20;
1119 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001120 strncpy((char *)vendor, "SMSC", max_vendor_len);
1121 strncpy((char *)product, "Flash Media Cntrller",
1122 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001123 }
1124}
1125#endif /* CONFIG_USB_BIN_FIXUP */
1126
Simon Glass07b2b782016-02-29 15:25:58 -07001127#ifdef CONFIG_BLK
1128static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1129 lbaint_t blkcnt, void *buffer)
1130#else
Simon Glass4101f682016-02-29 15:25:34 -07001131static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001132 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001133#endif
wdenkaffae2b2002-08-17 09:36:01 +00001134{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001135 lbaint_t start, blks;
1136 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001137 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001138 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001139 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001140 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001141 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001142#ifdef CONFIG_BLK
1143 struct blk_desc *block_dev;
1144#endif
wdenkf8d813e2004-03-02 14:05:39 +00001145
1146 if (blkcnt == 0)
1147 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001148 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001149#ifdef CONFIG_BLK
1150 block_dev = dev_get_uclass_platdata(dev);
1151 udev = dev_get_parent_priv(dev_get_parent(dev));
1152 debug("\nusb_read: udev %d\n", block_dev->devnum);
1153#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001154 debug("\nusb_read: udev %d\n", block_dev->devnum);
1155 udev = usb_dev_desc[block_dev->devnum].priv;
1156 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001157 debug("%s: No device\n", __func__);
1158 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001159 }
Simon Glass07b2b782016-02-29 15:25:58 -07001160#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001161 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001162
1163 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass9807c3b2016-02-29 15:25:54 -07001164 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001165 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001166 start = blknr;
1167 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001168
Simon Glass9807c3b2016-02-29 15:25:54 -07001169 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1170 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001171
wdenkaffae2b2002-08-17 09:36:01 +00001172 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001173 /* XXX need some comment here */
1174 retry = 2;
1175 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001176 if (blks > USB_MAX_XFER_BLK)
1177 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001178 else
1179 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001180retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001181 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001182 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001183 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001184 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001185 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301186 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001187 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001188 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001189 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001190 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001191 break;
1192 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001193 start += smallblks;
1194 blks -= smallblks;
1195 buf_addr += srb->datalen;
1196 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001197 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001198
Vivek Gautamceb49722013-04-12 16:34:33 +05301199 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001200 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301201 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001202
wdenkaffae2b2002-08-17 09:36:01 +00001203 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001204 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001205 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001206 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001207}
1208
Simon Glass07b2b782016-02-29 15:25:58 -07001209#ifdef CONFIG_BLK
1210static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1211 lbaint_t blkcnt, const void *buffer)
1212#else
Simon Glass4101f682016-02-29 15:25:34 -07001213static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001214 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001215#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301216{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001217 lbaint_t start, blks;
1218 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301219 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001220 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001221 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001222 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301223 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001224#ifdef CONFIG_BLK
1225 struct blk_desc *block_dev;
1226#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301227
1228 if (blkcnt == 0)
1229 return 0;
1230
Mahavir Jain127e1082009-11-03 12:22:10 +05301231 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001232#ifdef CONFIG_BLK
1233 block_dev = dev_get_uclass_platdata(dev);
1234 udev = dev_get_parent_priv(dev_get_parent(dev));
1235 debug("\nusb_read: udev %d\n", block_dev->devnum);
1236#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001237 debug("\nusb_read: udev %d\n", block_dev->devnum);
1238 udev = usb_dev_desc[block_dev->devnum].priv;
1239 if (!udev) {
1240 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001241 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001242 }
Simon Glass07b2b782016-02-29 15:25:58 -07001243#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001244 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301245
1246 usb_disable_asynch(1); /* asynch transfer not allowed */
1247
Simon Glass9807c3b2016-02-29 15:25:54 -07001248 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001249 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301250 start = blknr;
1251 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301252
Simon Glass9807c3b2016-02-29 15:25:54 -07001253 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1254 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301255
1256 do {
1257 /* If write fails retry for max retry count else
1258 * return with number of blocks written successfully.
1259 */
1260 retry = 2;
1261 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001262 if (blks > USB_MAX_XFER_BLK)
1263 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301264 else
1265 smallblks = (unsigned short) blks;
1266retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001267 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301268 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001269 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301270 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001271 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301272 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001273 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301274 if (retry--)
1275 goto retry_it;
1276 blkcnt -= blks;
1277 break;
1278 }
1279 start += smallblks;
1280 blks -= smallblks;
1281 buf_addr += srb->datalen;
1282 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001283 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301284
Simon Glass4fd074d2014-10-15 04:38:38 -06001285 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1286 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301287
1288 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001289 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001290 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301291 return blkcnt;
1292
1293}
wdenkaffae2b2002-08-17 09:36:01 +00001294
1295/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001296int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1297 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001298{
Tom Rix8f8bd562009-10-31 12:37:38 -05001299 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001300 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301301 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001302 unsigned int flags = 0;
1303
wdenkaffae2b2002-08-17 09:36:01 +00001304 /* let's examine the device now */
1305 iface = &dev->config.if_desc[ifnum];
1306
wdenkaffae2b2002-08-17 09:36:01 +00001307 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001308 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1309 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1310 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001311 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001312 /* if it's not a mass storage, we go no further */
1313 return 0;
1314 }
1315
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001316 memset(ss, 0, sizeof(struct us_data));
1317
wdenkaffae2b2002-08-17 09:36:01 +00001318 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301319 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001320
1321 /* Initialize the us_data structure with some useful info */
1322 ss->flags = flags;
1323 ss->ifnum = ifnum;
1324 ss->pusb_dev = dev;
1325 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001326 ss->subclass = iface->desc.bInterfaceSubClass;
1327 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001328
1329 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301330 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001331 switch (ss->protocol) {
1332 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301333 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001334 ss->transport = usb_stor_CB_transport;
1335 ss->transport_reset = usb_stor_CB_reset;
1336 break;
1337
1338 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301339 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001340 ss->transport = usb_stor_CB_transport;
1341 ss->transport_reset = usb_stor_CB_reset;
1342 break;
wdenk149dded2003-09-10 18:20:28 +00001343 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301344 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001345 ss->transport = usb_stor_BBB_transport;
1346 ss->transport_reset = usb_stor_BBB_reset;
1347 break;
wdenkaffae2b2002-08-17 09:36:01 +00001348 default:
wdenk80885a92004-02-26 23:46:20 +00001349 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001350 return 0;
1351 break;
1352 }
1353
1354 /*
1355 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1356 * An optional interrupt is OK (necessary for CBI protocol).
1357 * We will ignore any others.
1358 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001359 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301360 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001361 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301362 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001363 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301364 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1365 ss->ep_in = ep_desc->bEndpointAddress &
1366 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001367 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001368 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301369 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001370 USB_ENDPOINT_NUMBER_MASK;
1371 }
1372
1373 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301374 if ((ep_desc->bmAttributes &
1375 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1376 ss->ep_int = ep_desc->bEndpointAddress &
1377 USB_ENDPOINT_NUMBER_MASK;
1378 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001379 }
1380 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301381 debug("Endpoints In %d Out %d Int %d\n",
1382 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001383
1384 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001385 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001386 !ss->ep_in || !ss->ep_out ||
1387 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301388 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001389 return 0;
1390 }
1391 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001392 /* We only handle certain protocols. Currently, these are
1393 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001394 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001395 */
wdenk80885a92004-02-26 23:46:20 +00001396 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1397 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001398 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001399 return 0;
1400 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001401 if (ss->ep_int) {
1402 /* we had found an interrupt endpoint, prepare irq pipe
1403 * set up the IRQ pipe and handler
1404 */
wdenkaffae2b2002-08-17 09:36:01 +00001405 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1406 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1407 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001408 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001409 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001410 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001411 return 1;
1412}
1413
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001414int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001415 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001416{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001417 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001418 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1419 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1420 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001421 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001422
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001423 pccb->pdata = usb_stor_buf;
1424
1425 dev_desc->target = dev->devnum;
1426 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301427 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001428
Simon Glass1d5827a2015-03-25 12:22:12 -06001429 if (usb_inquiry(pccb, ss)) {
1430 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001431 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001432 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001433
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001434 perq = usb_stor_buf[0];
1435 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001436
Soeren Moch6a559bb2014-11-08 07:02:14 +01001437 /*
1438 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1439 * they would not respond to test_unit_ready .
1440 */
1441 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001442 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001443 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001444 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001445 if ((modi&0x80) == 0x80) {
1446 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001447 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001449 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1450 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1451 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001452 dev_desc->vendor[8] = 0;
1453 dev_desc->product[16] = 0;
1454 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001455#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001456 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1457 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001458#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301459 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1460 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001461 if (usb_test_unit_ready(pccb, ss)) {
1462 printf("Device NOT ready\n"
1463 " Request Sense returned %02X %02X %02X\n",
1464 pccb->sense_buf[2], pccb->sense_buf[12],
1465 pccb->sense_buf[13]);
1466 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001467 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001468 return 1;
1469 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001470 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001471 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001472 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001473 memset(pccb->pdata, 0, 8);
1474 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001475 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001476 cap[0] = 2880;
1477 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001478 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001479 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001480 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001481#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001482 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1483 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001484
Christian Eggersc9182612008-05-21 22:12:00 +02001485 cap[0] = cpu_to_be32(cap[0]);
1486 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001487#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001488
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001489 capacity = be32_to_cpu(cap[0]) + 1;
1490 blksz = be32_to_cpu(cap[1]);
1491
1492 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1493 dev_desc->lba = capacity;
1494 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001495 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001496 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301497 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001498
wdenkaffae2b2002-08-17 09:36:01 +00001499 return 1;
1500}
Simon Glassacf277a2015-03-25 12:22:16 -06001501
1502#ifdef CONFIG_DM_USB
1503
1504static int usb_mass_storage_probe(struct udevice *dev)
1505{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001506 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001507 int ret;
1508
1509 usb_disable_asynch(1); /* asynch transfer not allowed */
1510 ret = usb_stor_probe_device(udev);
1511 usb_disable_asynch(0); /* asynch transfer allowed */
1512
1513 return ret;
1514}
1515
1516static const struct udevice_id usb_mass_storage_ids[] = {
1517 { .compatible = "usb-mass-storage" },
1518 { }
1519};
1520
1521U_BOOT_DRIVER(usb_mass_storage) = {
1522 .name = "usb_mass_storage",
1523 .id = UCLASS_MASS_STORAGE,
1524 .of_match = usb_mass_storage_ids,
1525 .probe = usb_mass_storage_probe,
Simon Glass07b2b782016-02-29 15:25:58 -07001526#ifdef CONFIG_BLK
1527 .platdata_auto_alloc_size = sizeof(struct us_data),
1528#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001529};
1530
1531UCLASS_DRIVER(usb_mass_storage) = {
1532 .id = UCLASS_MASS_STORAGE,
1533 .name = "usb_mass_storage",
1534};
1535
1536static const struct usb_device_id mass_storage_id_table[] = {
1537 {
1538 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1539 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1540 },
1541 { } /* Terminating entry */
1542};
1543
Simon Glassabb59cf2015-07-06 16:47:51 -06001544U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001545#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001546
Simon Glass07b2b782016-02-29 15:25:58 -07001547#ifdef CONFIG_BLK
1548static const struct blk_ops usb_storage_ops = {
1549 .read = usb_stor_read,
1550 .write = usb_stor_write,
1551};
1552
1553U_BOOT_DRIVER(usb_storage_blk) = {
1554 .name = "usb_storage_blk",
1555 .id = UCLASS_BLK,
1556 .ops = &usb_storage_ops,
1557};
Simon Glassacf277a2015-03-25 12:22:16 -06001558#endif