blob: 7e6e52d2ec37a2383935721332a31e2636317e98 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk6a3d6b02005-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 Glassac9774e2015-03-25 12:22:16 -060012 * Driver model conversion:
13 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000014 *
wdenkde887eb2003-09-10 18:20:28 +000015 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020016 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000017 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020018 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000019 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000020 *
Wolfgang Denkd79de1d2013-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 */
wdenkde887eb2003-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.
wdenkde887eb2003-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 Glassac9774e2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060039#include <errno.h>
Simon Glassb43f7682014-10-15 04:38:38 -060040#include <inttypes.h>
Simon Glass332a9b62015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020043#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070046#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000047
Grant Likelyffc2dd72007-02-20 09:04:34 +010048#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000049#include <usb.h>
50
wdenk5f495752004-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 Frysinger165522b2010-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 Saxena6c9bb602012-04-03 14:56:06 +053066static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchi956a4352008-12-10 15:52:06 +010067static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000068
Michael Trimarchi956a4352008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
Simon Glass01f5be92016-02-29 15:25:58 -070071#ifndef CONFIG_BLK
Simon Glasse3394752016-02-29 15:25:34 -070072static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070073#endif
wdenkaffae2b2002-08-17 09:36:01 +000074
75struct us_data;
Michael Trimarchi956a4352008-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 Trimarchi956a4352008-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ébaudeaufbf909a2012-08-10 18:27:11 +020083# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-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ébaudeau938051f2012-08-10 18:26:50 +0200103#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000104/*
Benoît Thébaudeaudfa2bcc2012-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 Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000108 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200109#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200110#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200111#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200112#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000113
Simon Glass01f5be92016-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 Glass01f5be92016-02-29 15:25:58 -0700116#endif
wdenkaffae2b2002-08-17 09:36:01 +0000117
wdenk5f495752004-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 Trimarchi956a4352008-12-10 15:52:06 +0100122int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700123 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100124int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
125 struct us_data *ss);
Simon Glass01f5be92016-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 Glasse3394752016-02-29 15:25:34 -0700132static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700133 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700134static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700135 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700136#endif
wdenkaffae2b2002-08-17 09:36:01 +0000137void uhci_show_temp_int_td(void);
138
Kim Phillipsb052b602012-10-29 13:34:32 +0000139static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000140{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200141 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000142}
143
Michael Trimarchi956a4352008-12-10 15:52:06 +0100144/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200145 * show info on storage devices; 'usb start/init' must be invoked earlier
146 * as we only retrieve structures populated during devices initialization
147 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100148int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200149{
Simon Glass99e598e2016-02-29 15:25:54 -0700150 int count = 0;
Simon Glass01f5be92016-02-29 15:25:58 -0700151#ifdef CONFIG_BLK
152 struct udevice *dev;
153
154 for (blk_first_device(IF_TYPE_USB, &dev);
155 dev;
156 blk_next_device(&dev)) {
157 struct blk_desc *desc = dev_get_uclass_platdata(dev);
158
159 printf(" Device %d: ", desc->devnum);
160 dev_print(desc);
161 count++;
162 }
163#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200164 int i;
165
Aras Vaichas7ede1862008-03-25 12:09:07 +1100166 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200167 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100168 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200169 dev_print(&usb_dev_desc[i]);
170 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100171 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100172 }
Simon Glass01f5be92016-02-29 15:25:58 -0700173#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700174 if (!count) {
175 printf("No storage devices, perhaps not 'usb start'ed..?\n");
176 return 1;
177 }
178
Simon Glass8c6c0742016-03-16 07:45:44 -0600179 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200180}
181
Ludovic Courtès134396c2010-10-05 22:04:26 +0200182static unsigned int usb_get_max_lun(struct us_data *us)
183{
184 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530185 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200186 len = usb_control_msg(us->pusb_dev,
187 usb_rcvctrlpipe(us->pusb_dev, 0),
188 US_BBB_GET_MAX_LUN,
189 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
190 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530191 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200192 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530193 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530194 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200195}
196
Simon Glass99e598e2016-02-29 15:25:54 -0700197static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600198{
Simon Glass99e598e2016-02-29 15:25:54 -0700199 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700200
201#ifdef CONFIG_BLK
202 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700203 int ret;
204#else
Simon Glass99e598e2016-02-29 15:25:54 -0700205 int start;
206
207 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600208 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700209#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600210
Simon Glass01f5be92016-02-29 15:25:58 -0700211 debug("\n\nProbing for storage\n");
212#ifdef CONFIG_BLK
213 /*
214 * We store the us_data in the mass storage device's platdata. It
215 * is shared by all LUNs (block devices) attached to this mass storage
216 * device.
217 */
218 data = dev_get_platdata(udev->dev);
219 if (!usb_storage_probe(udev, 0, data))
220 return 0;
221 max_lun = usb_get_max_lun(data);
222 for (lun = 0; lun <= max_lun; lun++) {
223 struct blk_desc *blkdev;
224 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600225 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700226
Simon Glass966b6952016-05-01 11:36:29 -0600227 snprintf(str, sizeof(str), "lun%d", lun);
228 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
229 IF_TYPE_USB, usb_max_devs, 512, 0,
230 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700231 if (ret) {
232 debug("Cannot bind driver\n");
233 return ret;
234 }
235
236 blkdev = dev_get_uclass_platdata(dev);
237 blkdev->target = 0xff;
238 blkdev->lun = lun;
239
240 ret = usb_stor_get_info(udev, data, blkdev);
241 if (ret == 1)
242 ret = blk_prepare_device(dev);
243 if (!ret) {
244 usb_max_devs++;
245 debug("%s: Found device %p\n", __func__, udev);
246 } else {
247 debug("usb_stor_get_info: Invalid device\n");
248 ret = device_unbind(dev);
249 if (ret)
250 return ret;
251 }
252 }
253#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700254 /* We don't have space to even probe if we hit the maximum */
255 if (usb_max_devs == USB_MAX_STOR_DEV) {
256 printf("max USB Storage Device reached: %d stopping\n",
257 usb_max_devs);
258 return -ENOSPC;
259 }
260
Simon Glass99e598e2016-02-29 15:25:54 -0700261 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
262 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600263
Simon Glass99e598e2016-02-29 15:25:54 -0700264 /*
265 * OK, it's a storage device. Iterate over its LUNs and populate
266 * usb_dev_desc'
267 */
268 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600269
Simon Glass99e598e2016-02-29 15:25:54 -0700270 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
271 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
272 lun++) {
273 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600274
Simon Glass99e598e2016-02-29 15:25:54 -0700275 blkdev = &usb_dev_desc[usb_max_devs];
276 memset(blkdev, '\0', sizeof(struct blk_desc));
277 blkdev->if_type = IF_TYPE_USB;
278 blkdev->devnum = usb_max_devs;
279 blkdev->part_type = PART_TYPE_UNKNOWN;
280 blkdev->target = 0xff;
281 blkdev->type = DEV_TYPE_UNKNOWN;
282 blkdev->block_read = usb_stor_read;
283 blkdev->block_write = usb_stor_write;
284 blkdev->lun = lun;
285 blkdev->priv = udev;
286
287 if (usb_stor_get_info(udev, &usb_stor[start],
288 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700289 debug("partype: %d\n", blkdev->part_type);
290 part_init(blkdev);
291 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700292 usb_max_devs++;
293 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600294 }
295 }
Simon Glass01f5be92016-02-29 15:25:58 -0700296#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600297
Simon Glassdf7d34f2015-03-25 12:22:15 -0600298 return 0;
299}
300
301void usb_stor_reset(void)
302{
303 usb_max_devs = 0;
304}
305
Simon Glassac9774e2015-03-25 12:22:16 -0600306#ifndef CONFIG_DM_USB
Michael Trimarchi956a4352008-12-10 15:52:06 +0100307/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200308 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000309 * to the user if mode = 1
310 * returns current device or -1 if no
311 */
312int usb_stor_scan(int mode)
313{
Simon Glass0f50b162015-04-16 17:27:34 -0600314 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000315
Michael Trimarchi956a4352008-12-10 15:52:06 +0100316 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200317 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100318
wdenkaffae2b2002-08-17 09:36:01 +0000319 usb_disable_asynch(1); /* asynch transfer not allowed */
320
Simon Glassdf7d34f2015-03-25 12:22:15 -0600321 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100322 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600323 struct usb_device *dev;
324
Michael Trimarchi956a4352008-12-10 15:52:06 +0100325 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530326 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600327 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000328 break;
wdenkaffae2b2002-08-17 09:36:01 +0000329 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200330
wdenkaffae2b2002-08-17 09:36:01 +0000331 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200332 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100333 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100335 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000336}
Simon Glassac9774e2015-03-25 12:22:16 -0600337#endif
wdenkaffae2b2002-08-17 09:36:01 +0000338
339static int usb_stor_irq(struct usb_device *dev)
340{
341 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100342 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000343
Michael Trimarchi956a4352008-12-10 15:52:06 +0100344 if (us->ip_wanted)
345 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000346 return 0;
347}
348
349
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530350#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000351
Michael Trimarchi956a4352008-12-10 15:52:06 +0100352static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000353{
354 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100355 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
356 for (i = 0; i < 12; i++)
357 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000358 printf("\n");
359}
360
361static void display_int_status(unsigned long tmp)
362{
363 printf("Status: %s %s %s %s %s %s %s\n",
364 (tmp & USB_ST_ACTIVE) ? "Active" : "",
365 (tmp & USB_ST_STALLED) ? "Stalled" : "",
366 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
367 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
368 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
369 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
370 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
371}
372#endif
373/***********************************************************************
374 * Data transfer routines
375 ***********************************************************************/
376
377static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
378{
379 int max_size;
380 int this_xfer;
381 int result;
382 int partial;
383 int maxtry;
384 int stat;
385
386 /* determine the maximum packet size for these transfers */
387 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
388
389 /* while we have data left to transfer */
390 while (length) {
391
392 /* calculate how long this will be -- maximum or a remainder */
393 this_xfer = length > max_size ? max_size : length;
394 length -= this_xfer;
395
396 /* setup the retry counter */
397 maxtry = 10;
398
399 /* set up the transfer loop */
400 do {
401 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600402 debug("Bulk xfer 0x%lx(%d) try #%d\n",
403 (ulong)map_to_sysmem(buf), this_xfer,
404 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000405 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100406 this_xfer, &partial,
407 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530408 debug("bulk_msg returned %d xferred %d/%d\n",
409 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100410 if (us->pusb_dev->status != 0) {
411 /* if we stall, we need to clear it before
412 * we go on
413 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530414#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000415 display_int_status(us->pusb_dev->status);
416#endif
417 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530418 debug("stalled ->clearing endpoint" \
419 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000420 stat = us->pusb_dev->status;
421 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100422 us->pusb_dev->status = stat;
423 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530424 debug("bulk transferred" \
425 "with error %lX," \
426 " but data ok\n",
427 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000428 return 0;
429 }
430 else
431 return result;
432 }
433 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530434 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000435 return result;
436 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530437 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100438 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530439 debug(" %ld, but data ok\n",
440 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000441 return 0;
442 }
443 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530444 debug(" %ld, data %d\n",
445 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000446 if (!maxtry--)
447 return result;
448 }
449 /* update to show what data was transferred */
450 this_xfer -= partial;
451 buf += partial;
452 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100453 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000454 }
455
456 /* if we get here, we're done and successful */
457 return 0;
458}
459
wdenkde887eb2003-09-10 18:20:28 +0000460static int usb_stor_BBB_reset(struct us_data *us)
461{
462 int result;
463 unsigned int pipe;
464
465 /*
466 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
467 *
468 * For Reset Recovery the host shall issue in the following order:
469 * a) a Bulk-Only Mass Storage Reset
470 * b) a Clear Feature HALT to the Bulk-In endpoint
471 * c) a Clear Feature HALT to the Bulk-Out endpoint
472 *
473 * This is done in 3 steps.
474 *
475 * If the reset doesn't succeed, the device should be port reset.
476 *
477 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
478 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530479 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100480 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
481 US_BBB_RESET,
482 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000483 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200484
Michael Trimarchi956a4352008-12-10 15:52:06 +0100485 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530486 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000487 return -1;
488 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200489
wdenkde887eb2003-09-10 18:20:28 +0000490 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX reset\n",
493 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000494 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
495 result = usb_clear_halt(us->pusb_dev, pipe);
496 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000497 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530498 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
499 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000500 /* long wait for reset */
501 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
502 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000503 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530504 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
505 result, us->pusb_dev->status);
506 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000507 return 0;
508}
509
wdenkaffae2b2002-08-17 09:36:01 +0000510/* FIXME: this reset function doesn't really reset the port, and it
511 * should. Actually it should probably do what it's doing here, and
512 * reset the port physically
513 */
514static int usb_stor_CB_reset(struct us_data *us)
515{
516 unsigned char cmd[12];
517 int result;
518
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530519 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100520 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000521 cmd[0] = SCSI_SEND_DIAG;
522 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100523 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
524 US_CBI_ADSC,
525 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
526 0, us->ifnum, cmd, sizeof(cmd),
527 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000528
529 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000530 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530531 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
532 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000533 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
534 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
535
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530536 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000537 return 0;
538}
539
wdenkde887eb2003-09-10 18:20:28 +0000540/*
541 * Set up the command for a BBB device. Note that the actual SCSI
542 * command is copied into cbw.CBWCDB.
543 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000544static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000545{
546 int result;
547 int actlen;
548 int dir_in;
549 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600550 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000551
552 dir_in = US_DIRECTION(srb->cmd[0]);
553
554#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530555 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100556 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
557 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000558 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100559 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000560 printf("cmd[%d] %#x ", result, srb->cmd[result]);
561 printf("\n");
562 }
563#endif
564 /* sanity checks */
565 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530566 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000567 return -1;
568 }
569
570 /* always OUT to the ep */
571 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
572
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530573 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
574 cbw->dCBWTag = cpu_to_le32(CBWTag++);
575 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
576 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
577 cbw->bCBWLUN = srb->lun;
578 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000579 /* copy the command data into the CBW command data buffer */
580 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300581
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530582 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
583 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100584 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000585 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530586 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000587 return result;
588}
589
wdenkaffae2b2002-08-17 09:36:01 +0000590/* FIXME: we also need a CBI_command which sets up the completion
591 * interrupt, and waits for it
592 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000593static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000594{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200595 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100596 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000597 unsigned int pipe;
598 unsigned long status;
599
Michael Trimarchi956a4352008-12-10 15:52:06 +0100600 retry = 5;
601 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000602
Michael Trimarchi956a4352008-12-10 15:52:06 +0100603 if (dir_in)
604 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
605 else
606 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
607
608 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530609 debug("CBI gets a command: Try %d\n", 5 - retry);
610#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000611 usb_show_srb(srb);
612#endif
613 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100614 result = usb_control_msg(us->pusb_dev,
615 usb_sndctrlpipe(us->pusb_dev , 0),
616 US_CBI_ADSC,
617 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000618 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100619 srb->cmd, srb->cmdlen,
620 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530621 debug("CB_transport: control msg returned %d, status %lX\n",
622 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000623 /* check the return code for the command */
624 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100625 if (us->pusb_dev->status & USB_ST_STALLED) {
626 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530627 debug(" stall during command found," \
628 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100629 usb_clear_halt(us->pusb_dev,
630 usb_sndctrlpipe(us->pusb_dev, 0));
631 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000632 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530633 debug(" error during command %02X" \
634 " Stat = %lX\n", srb->cmd[0],
635 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000636 return result;
637 }
638 /* transfer the data payload for this command, if one exists*/
639
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530640 debug("CB_transport: control msg returned %d," \
641 " direction is %s to go 0x%lx\n", result,
642 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000643 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100644 result = us_one_transfer(us, pipe, (char *)srb->pdata,
645 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530646 debug("CBI attempted to transfer data," \
647 " result is %d status %lX, len %d\n",
648 result, us->pusb_dev->status,
649 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100650 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000651 break;
652 } /* if (srb->datalen) */
653 else
654 break;
655 }
656 /* return result */
657
658 return result;
659}
660
661
Kim Phillipsb052b602012-10-29 13:34:32 +0000662static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000663{
664 int timeout;
665
wdenk5f495752004-02-26 23:46:20 +0000666 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100667 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000668 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
669 timeout = 1000;
670 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300671 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000672 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000673 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000674 }
675 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100676 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000677 us->ip_wanted = 0;
678 return USB_STOR_TRANSPORT_ERROR;
679 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700680 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530681 us->ip_data, us->pusb_dev->irq_act_len,
682 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000683 /* UFI gives us ASC and ASCQ, like a request sense */
684 if (us->subclass == US_SC_UFI) {
685 if (srb->cmd[0] == SCSI_REQ_SENSE ||
686 srb->cmd[0] == SCSI_INQUIRY)
687 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000688 else if (us->ip_data)
689 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000690 else
wdenk5f495752004-02-26 23:46:20 +0000691 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000692 }
693 /* otherwise, we interpret the data normally */
694 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000695 case 0x0001:
696 return USB_STOR_TRANSPORT_GOOD;
697 case 0x0002:
698 return USB_STOR_TRANSPORT_FAILED;
699 default:
700 return USB_STOR_TRANSPORT_ERROR;
701 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000702 return USB_STOR_TRANSPORT_ERROR;
703}
704
705#define USB_TRANSPORT_UNKNOWN_RETRY 5
706#define USB_TRANSPORT_NOT_READY_RETRY 10
707
wdenkde887eb2003-09-10 18:20:28 +0000708/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000709static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000710{
711 int result;
712
713 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100714 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000715 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000716 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000717 return result;
718}
719
Kim Phillipsb052b602012-10-29 13:34:32 +0000720static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000721{
722 int result, retry;
723 int dir_in;
724 int actlen, data_actlen;
725 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600726 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000727#ifdef BBB_XPORT_TRACE
728 unsigned char *ptr;
729 int index;
730#endif
731
732 dir_in = US_DIRECTION(srb->cmd[0]);
733
734 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530735 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000736 result = usb_stor_BBB_comdat(srb, us);
737 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530738 debug("failed to send CBW status %ld\n",
739 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000740 usb_stor_BBB_reset(us);
741 return USB_STOR_TRANSPORT_FAILED;
742 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200743 if (!(us->flags & USB_READY))
744 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000745 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
746 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
747 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000748 data_actlen = 0;
749 /* no data, go immediately to the STATUS phase */
750 if (srb->datalen == 0)
751 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530752 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000753 if (dir_in)
754 pipe = pipein;
755 else
756 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300757
Michael Trimarchi956a4352008-12-10 15:52:06 +0100758 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
759 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000760 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100761 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530762 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000763 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100764 result = usb_stor_BBB_clear_endpt_stall(us,
765 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000766 if (result >= 0)
767 /* continue on to STATUS phase */
768 goto st;
769 }
770 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530771 debug("usb_bulk_msg error status %ld\n",
772 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000773 usb_stor_BBB_reset(us);
774 return USB_STOR_TRANSPORT_FAILED;
775 }
776#ifdef BBB_XPORT_TRACE
777 for (index = 0; index < data_actlen; index++)
778 printf("pdata[%d] %#x ", index, srb->pdata[index]);
779 printf("\n");
780#endif
781 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100782st:
wdenkde887eb2003-09-10 18:20:28 +0000783 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100784again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530785 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530786 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200787 &actlen, USB_CNTL_TIMEOUT*5);
788
wdenkde887eb2003-09-10 18:20:28 +0000789 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100790 if ((result < 0) && (retry < 1) &&
791 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530792 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000793 /* clear the STALL on the endpoint */
794 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
795 if (result >= 0 && (retry++ < 1))
796 /* do a retry */
797 goto again;
798 }
799 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530800 debug("usb_bulk_msg error status %ld\n",
801 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000802 usb_stor_BBB_reset(us);
803 return USB_STOR_TRANSPORT_FAILED;
804 }
805#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530806 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000807 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
808 printf("ptr[%d] %#x ", index, ptr[index]);
809 printf("\n");
810#endif
811 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530812 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000813 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
814 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530815 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530816 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000817 usb_stor_BBB_reset(us);
818 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530819 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530820 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000821 usb_stor_BBB_reset(us);
822 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530823 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530824 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000825 usb_stor_BBB_reset(us);
826 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530827 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530828 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000829 usb_stor_BBB_reset(us);
830 return USB_STOR_TRANSPORT_FAILED;
831 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530832 debug("transferred %dB instead of %ldB\n",
833 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000834 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530835 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530836 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000837 return USB_STOR_TRANSPORT_FAILED;
838 }
839
840 return result;
841}
842
Kim Phillipsb052b602012-10-29 13:34:32 +0000843static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000844{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000846 ccb *psrb;
847 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000849
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200850 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100851 status = USB_STOR_TRANSPORT_GOOD;
852 retry = 0;
853 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000854 /* issue the command */
855do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100856 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530857 debug("command / Data returned %d, status %lX\n",
858 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000859 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100860 if (us->protocol == US_PR_CBI) {
861 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000862 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100863 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530864 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000865 return status;
866 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100867 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
868 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
869 if (!us->ip_data) {
870 /* if the status is good, report it */
871 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530872 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000873 return status;
874 }
875 }
876 }
877 /* do we have to issue an auto request? */
878 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100879 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530880 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000881 us->transport_reset(us);
882 return USB_STOR_TRANSPORT_ERROR;
883 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100884 if ((us->protocol == US_PR_CBI) &&
885 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
886 (srb->cmd[0] == SCSI_INQUIRY))) {
887 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530888 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000889 return USB_STOR_TRANSPORT_GOOD;
890 }
891 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100892 memset(&psrb->cmd[0], 0, 12);
893 psrb->cmd[0] = SCSI_REQ_SENSE;
894 psrb->cmd[1] = srb->lun << 5;
895 psrb->cmd[4] = 18;
896 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200897 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100898 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000899 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100900 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530901 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000902 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903 if (us->protocol == US_PR_CBI)
904 status = usb_stor_CBI_get_status(psrb, us);
905
906 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530907 debug(" AUTO REQUEST ERROR %ld\n",
908 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000909 return USB_STOR_TRANSPORT_ERROR;
910 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530911 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
912 srb->sense_buf[0], srb->sense_buf[2],
913 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000914 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100915 if ((srb->sense_buf[2] == 0) &&
916 (srb->sense_buf[12] == 0) &&
917 (srb->sense_buf[13] == 0)) {
918 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000919 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100920 }
921
wdenkaffae2b2002-08-17 09:36:01 +0000922 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100923 switch (srb->sense_buf[2]) {
924 case 0x01:
925 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000926 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000927 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100928 case 0x02:
929 /* Not Ready */
930 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
931 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
932 " 0x%02X (NOT READY)\n", srb->cmd[0],
933 srb->sense_buf[0], srb->sense_buf[2],
934 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000935 return USB_STOR_TRANSPORT_FAILED;
936 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000937 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000938 goto do_retry;
939 }
940 break;
941 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100942 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
943 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
944 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
945 srb->sense_buf[2], srb->sense_buf[12],
946 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000947 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100948 } else
wdenkde887eb2003-09-10 18:20:28 +0000949 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000950 break;
wdenkaffae2b2002-08-17 09:36:01 +0000951 }
952 return USB_STOR_TRANSPORT_FAILED;
953}
954
955
Michael Trimarchi956a4352008-12-10 15:52:06 +0100956static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000957{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100958 int retry, i;
959 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000960 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100961 memset(&srb->cmd[0], 0, 12);
962 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200963 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100964 srb->cmd[4] = 36;
965 srb->datalen = 36;
966 srb->cmdlen = 12;
967 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530968 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100969 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000970 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200971 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000972
Michael Trimarchi956a4352008-12-10 15:52:06 +0100973 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000974 printf("error in inquiry\n");
975 return -1;
976 }
977 return 0;
978}
979
Michael Trimarchi956a4352008-12-10 15:52:06 +0100980static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000981{
982 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000983
Michael Trimarchi956a4352008-12-10 15:52:06 +0100984 ptr = (char *)srb->pdata;
985 memset(&srb->cmd[0], 0, 12);
986 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200987 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 srb->cmd[4] = 18;
989 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200990 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100991 srb->cmdlen = 12;
992 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530993 debug("Request Sense returned %02X %02X %02X\n",
994 srb->sense_buf[2], srb->sense_buf[12],
995 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100996 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000997 return 0;
998}
999
Michael Trimarchi956a4352008-12-10 15:52:06 +01001000static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001001{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001002 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001003
wdenkaffae2b2002-08-17 09:36:01 +00001004 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001005 memset(&srb->cmd[0], 0, 12);
1006 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001007 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 srb->datalen = 0;
1009 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001010 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1011 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001012 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001013 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001014 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001015 /*
1016 * Check the Key Code Qualifier, if it matches
1017 * "Not Ready - medium not present"
1018 * (the sense Key equals 0x2 and the ASC is 0x3a)
1019 * return immediately as the medium being absent won't change
1020 * unless there is a user action.
1021 */
1022 if ((srb->sense_buf[2] == 0x02) &&
1023 (srb->sense_buf[12] == 0x3a))
1024 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001025 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001026 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001027
wdenkaffae2b2002-08-17 09:36:01 +00001028 return -1;
1029}
1030
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001032{
1033 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001034 /* XXX retries */
1035 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001036 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001037 memset(&srb->cmd[0], 0, 12);
1038 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001039 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001040 srb->datalen = 8;
1041 srb->cmdlen = 12;
1042 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001043 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001044 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001045
wdenkaffae2b2002-08-17 09:36:01 +00001046 return -1;
1047}
1048
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
1050 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001051{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001052 memset(&srb->cmd[0], 0, 12);
1053 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001054 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001055 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1056 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1057 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1058 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1059 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1060 srb->cmd[8] = (unsigned char) blocks & 0xff;
1061 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301062 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001063 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001064}
1065
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301066static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1067 unsigned short blocks)
1068{
1069 memset(&srb->cmd[0], 0, 12);
1070 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001071 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301072 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1073 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1074 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1075 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1076 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1077 srb->cmd[8] = (unsigned char) blocks & 0xff;
1078 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301079 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301080 return ss->transport(srb, ss);
1081}
1082
wdenkaffae2b2002-08-17 09:36:01 +00001083
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001084#ifdef CONFIG_USB_BIN_FIXUP
1085/*
1086 * Some USB storage devices queried for SCSI identification data respond with
1087 * binary strings, which if output to the console freeze the terminal. The
1088 * workaround is to modify the vendor and product strings read from such
1089 * device with proper values (as reported by 'usb info').
1090 *
1091 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001092 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001093 */
1094static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1095 unsigned char vendor[],
1096 unsigned char product[]) {
1097 const unsigned char max_vendor_len = 40;
1098 const unsigned char max_product_len = 20;
1099 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001100 strncpy((char *)vendor, "SMSC", max_vendor_len);
1101 strncpy((char *)product, "Flash Media Cntrller",
1102 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001103 }
1104}
1105#endif /* CONFIG_USB_BIN_FIXUP */
1106
Simon Glass01f5be92016-02-29 15:25:58 -07001107#ifdef CONFIG_BLK
1108static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1109 lbaint_t blkcnt, void *buffer)
1110#else
Simon Glasse3394752016-02-29 15:25:34 -07001111static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001112 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001113#endif
wdenkaffae2b2002-08-17 09:36:01 +00001114{
Gabe Black7d077682012-10-12 14:26:07 +00001115 lbaint_t start, blks;
1116 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001117 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001118 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001119 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001120 int retry;
wdenk0e2874cb2004-03-02 14:05:39 +00001121 ccb *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001122#ifdef CONFIG_BLK
1123 struct blk_desc *block_dev;
1124#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001125
1126 if (blkcnt == 0)
1127 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001128 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001129#ifdef CONFIG_BLK
1130 block_dev = dev_get_uclass_platdata(dev);
1131 udev = dev_get_parent_priv(dev_get_parent(dev));
1132 debug("\nusb_read: udev %d\n", block_dev->devnum);
1133#else
Simon Glass99e598e2016-02-29 15:25:54 -07001134 debug("\nusb_read: udev %d\n", block_dev->devnum);
1135 udev = usb_dev_desc[block_dev->devnum].priv;
1136 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001137 debug("%s: No device\n", __func__);
1138 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001139 }
Simon Glass01f5be92016-02-29 15:25:58 -07001140#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001141 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001142
1143 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass99e598e2016-02-29 15:25:54 -07001144 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001145 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001146 start = blknr;
1147 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001148
Simon Glass99e598e2016-02-29 15:25:54 -07001149 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1150 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001151
wdenkaffae2b2002-08-17 09:36:01 +00001152 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001153 /* XXX need some comment here */
1154 retry = 2;
1155 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001156 if (blks > USB_MAX_XFER_BLK)
1157 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001158 else
1159 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001160retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001161 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001162 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001163 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001164 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001165 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301166 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001167 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001168 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001169 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001170 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001171 break;
1172 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001173 start += smallblks;
1174 blks -= smallblks;
1175 buf_addr += srb->datalen;
1176 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001177 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001178
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301179 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001180 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301181 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001182
wdenkaffae2b2002-08-17 09:36:01 +00001183 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001184 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001185 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001186 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001187}
1188
Simon Glass01f5be92016-02-29 15:25:58 -07001189#ifdef CONFIG_BLK
1190static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1191 lbaint_t blkcnt, const void *buffer)
1192#else
Simon Glasse3394752016-02-29 15:25:34 -07001193static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001194 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001195#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301196{
Gabe Black7d077682012-10-12 14:26:07 +00001197 lbaint_t start, blks;
1198 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301199 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001200 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001201 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001202 int retry;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301203 ccb *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001204#ifdef CONFIG_BLK
1205 struct blk_desc *block_dev;
1206#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301207
1208 if (blkcnt == 0)
1209 return 0;
1210
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301211 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001212#ifdef CONFIG_BLK
1213 block_dev = dev_get_uclass_platdata(dev);
1214 udev = dev_get_parent_priv(dev_get_parent(dev));
1215 debug("\nusb_read: udev %d\n", block_dev->devnum);
1216#else
Simon Glass99e598e2016-02-29 15:25:54 -07001217 debug("\nusb_read: udev %d\n", block_dev->devnum);
1218 udev = usb_dev_desc[block_dev->devnum].priv;
1219 if (!udev) {
1220 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001221 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001222 }
Simon Glass01f5be92016-02-29 15:25:58 -07001223#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001224 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301225
1226 usb_disable_asynch(1); /* asynch transfer not allowed */
1227
Simon Glass99e598e2016-02-29 15:25:54 -07001228 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001229 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301230 start = blknr;
1231 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301232
Simon Glass99e598e2016-02-29 15:25:54 -07001233 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1234 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301235
1236 do {
1237 /* If write fails retry for max retry count else
1238 * return with number of blocks written successfully.
1239 */
1240 retry = 2;
1241 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001242 if (blks > USB_MAX_XFER_BLK)
1243 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301244 else
1245 smallblks = (unsigned short) blks;
1246retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001247 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301248 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001249 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301250 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001251 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301252 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001253 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301254 if (retry--)
1255 goto retry_it;
1256 blkcnt -= blks;
1257 break;
1258 }
1259 start += smallblks;
1260 blks -= smallblks;
1261 buf_addr += srb->datalen;
1262 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001263 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301264
Simon Glassb43f7682014-10-15 04:38:38 -06001265 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1266 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301267
1268 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001269 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001270 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301271 return blkcnt;
1272
1273}
wdenkaffae2b2002-08-17 09:36:01 +00001274
1275/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001276int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1277 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001278{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001279 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001280 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301281 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001282 unsigned int flags = 0;
1283
wdenkaffae2b2002-08-17 09:36:01 +00001284 /* let's examine the device now */
1285 iface = &dev->config.if_desc[ifnum];
1286
wdenkaffae2b2002-08-17 09:36:01 +00001287 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001288 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1289 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1290 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001291 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001292 /* if it's not a mass storage, we go no further */
1293 return 0;
1294 }
1295
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001296 memset(ss, 0, sizeof(struct us_data));
1297
wdenkaffae2b2002-08-17 09:36:01 +00001298 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301299 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001300
1301 /* Initialize the us_data structure with some useful info */
1302 ss->flags = flags;
1303 ss->ifnum = ifnum;
1304 ss->pusb_dev = dev;
1305 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001306 ss->subclass = iface->desc.bInterfaceSubClass;
1307 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001308
1309 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301310 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001311 switch (ss->protocol) {
1312 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301313 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001314 ss->transport = usb_stor_CB_transport;
1315 ss->transport_reset = usb_stor_CB_reset;
1316 break;
1317
1318 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301319 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001320 ss->transport = usb_stor_CB_transport;
1321 ss->transport_reset = usb_stor_CB_reset;
1322 break;
wdenkde887eb2003-09-10 18:20:28 +00001323 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301324 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001325 ss->transport = usb_stor_BBB_transport;
1326 ss->transport_reset = usb_stor_BBB_reset;
1327 break;
wdenkaffae2b2002-08-17 09:36:01 +00001328 default:
wdenk5f495752004-02-26 23:46:20 +00001329 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001330 return 0;
1331 break;
1332 }
1333
1334 /*
1335 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1336 * An optional interrupt is OK (necessary for CBI protocol).
1337 * We will ignore any others.
1338 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001339 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301340 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001341 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301342 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001343 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301344 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1345 ss->ep_in = ep_desc->bEndpointAddress &
1346 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001347 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001348 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301349 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001350 USB_ENDPOINT_NUMBER_MASK;
1351 }
1352
1353 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301354 if ((ep_desc->bmAttributes &
1355 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1356 ss->ep_int = ep_desc->bEndpointAddress &
1357 USB_ENDPOINT_NUMBER_MASK;
1358 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001359 }
1360 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301361 debug("Endpoints In %d Out %d Int %d\n",
1362 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001363
1364 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001365 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001366 !ss->ep_in || !ss->ep_out ||
1367 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301368 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001369 return 0;
1370 }
1371 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001372 /* We only handle certain protocols. Currently, these are
1373 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001374 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001375 */
wdenk5f495752004-02-26 23:46:20 +00001376 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1377 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001378 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001379 return 0;
1380 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001381 if (ss->ep_int) {
1382 /* we had found an interrupt endpoint, prepare irq pipe
1383 * set up the IRQ pipe and handler
1384 */
wdenkaffae2b2002-08-17 09:36:01 +00001385 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1386 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1387 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001388 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001389 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001390 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001391 return 1;
1392}
1393
Michael Trimarchi956a4352008-12-10 15:52:06 +01001394int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001395 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001396{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001397 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001398 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1399 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1400 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001401 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001402
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001403 pccb->pdata = usb_stor_buf;
1404
1405 dev_desc->target = dev->devnum;
1406 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301407 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001408
Simon Glass78330d62015-03-25 12:22:12 -06001409 if (usb_inquiry(pccb, ss)) {
1410 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001411 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001412 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001413
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001414 perq = usb_stor_buf[0];
1415 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001416
Soeren Moche4828002014-11-08 07:02:14 +01001417 /*
1418 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1419 * they would not respond to test_unit_ready .
1420 */
1421 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001422 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001423 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001424 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001425 if ((modi&0x80) == 0x80) {
1426 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001427 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001428 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001429 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1430 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1431 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001432 dev_desc->vendor[8] = 0;
1433 dev_desc->product[16] = 0;
1434 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001435#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001436 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1437 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001438#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301439 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1440 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001441 if (usb_test_unit_ready(pccb, ss)) {
1442 printf("Device NOT ready\n"
1443 " Request Sense returned %02X %02X %02X\n",
1444 pccb->sense_buf[2], pccb->sense_buf[12],
1445 pccb->sense_buf[13]);
1446 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001447 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001448 return 1;
1449 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001450 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001451 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001452 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001453 memset(pccb->pdata, 0, 8);
1454 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001455 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001456 cap[0] = 2880;
1457 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001458 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001459 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001460 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001461#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001462 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1463 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001464
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001465 cap[0] = cpu_to_be32(cap[0]);
1466 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001467#endif
1468
1469 capacity = be32_to_cpu(cap[0]) + 1;
1470 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001471
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001472 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1473 dev_desc->lba = capacity;
1474 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001475 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001476 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301477 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001478
wdenkaffae2b2002-08-17 09:36:01 +00001479 return 1;
1480}
Simon Glassac9774e2015-03-25 12:22:16 -06001481
1482#ifdef CONFIG_DM_USB
1483
1484static int usb_mass_storage_probe(struct udevice *dev)
1485{
Simon Glassde44acf2015-09-28 23:32:01 -06001486 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001487 int ret;
1488
1489 usb_disable_asynch(1); /* asynch transfer not allowed */
1490 ret = usb_stor_probe_device(udev);
1491 usb_disable_asynch(0); /* asynch transfer allowed */
1492
1493 return ret;
1494}
1495
1496static const struct udevice_id usb_mass_storage_ids[] = {
1497 { .compatible = "usb-mass-storage" },
1498 { }
1499};
1500
1501U_BOOT_DRIVER(usb_mass_storage) = {
1502 .name = "usb_mass_storage",
1503 .id = UCLASS_MASS_STORAGE,
1504 .of_match = usb_mass_storage_ids,
1505 .probe = usb_mass_storage_probe,
Simon Glass01f5be92016-02-29 15:25:58 -07001506#ifdef CONFIG_BLK
1507 .platdata_auto_alloc_size = sizeof(struct us_data),
1508#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001509};
1510
1511UCLASS_DRIVER(usb_mass_storage) = {
1512 .id = UCLASS_MASS_STORAGE,
1513 .name = "usb_mass_storage",
1514};
1515
1516static const struct usb_device_id mass_storage_id_table[] = {
1517 {
1518 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1519 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1520 },
1521 { } /* Terminating entry */
1522};
1523
Simon Glass46952fb2015-07-06 16:47:51 -06001524U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001525#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001526
Simon Glass01f5be92016-02-29 15:25:58 -07001527#ifdef CONFIG_BLK
1528static const struct blk_ops usb_storage_ops = {
1529 .read = usb_stor_read,
1530 .write = usb_stor_write,
1531};
1532
1533U_BOOT_DRIVER(usb_storage_blk) = {
1534 .name = "usb_storage_blk",
1535 .id = UCLASS_BLK,
1536 .ops = &usb_storage_ops,
1537};
Simon Glassd3171412016-05-01 11:36:06 -06001538#else
1539U_BOOT_LEGACY_BLK(usb) = {
1540 .if_typename = "usb",
1541 .if_type = IF_TYPE_USB,
1542 .max_devs = USB_MAX_STOR_DEV,
1543 .desc = usb_dev_desc,
1544};
Simon Glassac9774e2015-03-25 12:22:16 -06001545#endif