blob: b524a15e2bf93714c9ea758046d6c651decc4723 [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
Michael Trimarchi956a4352008-12-10 15:52:06 +0100306/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200307 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000308 * to the user if mode = 1
309 * returns current device or -1 if no
310 */
311int usb_stor_scan(int mode)
312{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100313 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200314 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100315
Michal Simekcd8f86f2016-12-21 09:35:08 +0100316#ifndef CONFIG_DM_USB
317 unsigned char i;
318
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 */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100332#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200333 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100334 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000335 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100336 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000337}
338
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{
wdenkde887eb2003-09-10 18:20:28 +0000711 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900712 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
713 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
714 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000715}
716
Kim Phillipsb052b602012-10-29 13:34:32 +0000717static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000718{
719 int result, retry;
720 int dir_in;
721 int actlen, data_actlen;
722 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600723 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000724#ifdef BBB_XPORT_TRACE
725 unsigned char *ptr;
726 int index;
727#endif
728
729 dir_in = US_DIRECTION(srb->cmd[0]);
730
731 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530732 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000733 result = usb_stor_BBB_comdat(srb, us);
734 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530735 debug("failed to send CBW status %ld\n",
736 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000737 usb_stor_BBB_reset(us);
738 return USB_STOR_TRANSPORT_FAILED;
739 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200740 if (!(us->flags & USB_READY))
741 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000742 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
743 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
744 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000745 data_actlen = 0;
746 /* no data, go immediately to the STATUS phase */
747 if (srb->datalen == 0)
748 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530749 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000750 if (dir_in)
751 pipe = pipein;
752 else
753 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300754
Michael Trimarchi956a4352008-12-10 15:52:06 +0100755 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
756 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000757 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100758 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530759 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000760 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100761 result = usb_stor_BBB_clear_endpt_stall(us,
762 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000763 if (result >= 0)
764 /* continue on to STATUS phase */
765 goto st;
766 }
767 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530768 debug("usb_bulk_msg error status %ld\n",
769 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000770 usb_stor_BBB_reset(us);
771 return USB_STOR_TRANSPORT_FAILED;
772 }
773#ifdef BBB_XPORT_TRACE
774 for (index = 0; index < data_actlen; index++)
775 printf("pdata[%d] %#x ", index, srb->pdata[index]);
776 printf("\n");
777#endif
778 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100779st:
wdenkde887eb2003-09-10 18:20:28 +0000780 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100781again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530782 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530783 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200784 &actlen, USB_CNTL_TIMEOUT*5);
785
wdenkde887eb2003-09-10 18:20:28 +0000786 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100787 if ((result < 0) && (retry < 1) &&
788 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530789 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000790 /* clear the STALL on the endpoint */
791 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
792 if (result >= 0 && (retry++ < 1))
793 /* do a retry */
794 goto again;
795 }
796 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530797 debug("usb_bulk_msg error status %ld\n",
798 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000799 usb_stor_BBB_reset(us);
800 return USB_STOR_TRANSPORT_FAILED;
801 }
802#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530803 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000804 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
805 printf("ptr[%d] %#x ", index, ptr[index]);
806 printf("\n");
807#endif
808 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530809 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000810 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
811 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530812 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530813 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000814 usb_stor_BBB_reset(us);
815 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530816 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530817 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000818 usb_stor_BBB_reset(us);
819 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530820 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530821 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000822 usb_stor_BBB_reset(us);
823 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530824 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530825 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000826 usb_stor_BBB_reset(us);
827 return USB_STOR_TRANSPORT_FAILED;
828 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530829 debug("transferred %dB instead of %ldB\n",
830 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000831 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530832 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530833 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000834 return USB_STOR_TRANSPORT_FAILED;
835 }
836
837 return result;
838}
839
Kim Phillipsb052b602012-10-29 13:34:32 +0000840static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000841{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100842 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000843 ccb *psrb;
844 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000846
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200847 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 status = USB_STOR_TRANSPORT_GOOD;
849 retry = 0;
850 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000851 /* issue the command */
852do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100853 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530854 debug("command / Data returned %d, status %lX\n",
855 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000856 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100857 if (us->protocol == US_PR_CBI) {
858 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000859 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100860 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530861 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000862 return status;
863 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100864 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
865 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
866 if (!us->ip_data) {
867 /* if the status is good, report it */
868 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530869 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000870 return status;
871 }
872 }
873 }
874 /* do we have to issue an auto request? */
875 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100876 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530877 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000878 us->transport_reset(us);
879 return USB_STOR_TRANSPORT_ERROR;
880 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 if ((us->protocol == US_PR_CBI) &&
882 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
883 (srb->cmd[0] == SCSI_INQUIRY))) {
884 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530885 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000886 return USB_STOR_TRANSPORT_GOOD;
887 }
888 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100889 memset(&psrb->cmd[0], 0, 12);
890 psrb->cmd[0] = SCSI_REQ_SENSE;
891 psrb->cmd[1] = srb->lun << 5;
892 psrb->cmd[4] = 18;
893 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200894 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100895 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000896 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100897 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530898 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000899 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100900 if (us->protocol == US_PR_CBI)
901 status = usb_stor_CBI_get_status(psrb, us);
902
903 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530904 debug(" AUTO REQUEST ERROR %ld\n",
905 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000906 return USB_STOR_TRANSPORT_ERROR;
907 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530908 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
909 srb->sense_buf[0], srb->sense_buf[2],
910 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000911 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100912 if ((srb->sense_buf[2] == 0) &&
913 (srb->sense_buf[12] == 0) &&
914 (srb->sense_buf[13] == 0)) {
915 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000916 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100917 }
918
wdenkaffae2b2002-08-17 09:36:01 +0000919 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100920 switch (srb->sense_buf[2]) {
921 case 0x01:
922 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000923 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000924 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100925 case 0x02:
926 /* Not Ready */
927 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
928 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
929 " 0x%02X (NOT READY)\n", srb->cmd[0],
930 srb->sense_buf[0], srb->sense_buf[2],
931 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000932 return USB_STOR_TRANSPORT_FAILED;
933 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000934 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000935 goto do_retry;
936 }
937 break;
938 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100939 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
940 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
941 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
942 srb->sense_buf[2], srb->sense_buf[12],
943 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000944 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100945 } else
wdenkde887eb2003-09-10 18:20:28 +0000946 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000947 break;
wdenkaffae2b2002-08-17 09:36:01 +0000948 }
949 return USB_STOR_TRANSPORT_FAILED;
950}
951
952
Michael Trimarchi956a4352008-12-10 15:52:06 +0100953static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000954{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100955 int retry, i;
956 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000957 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100958 memset(&srb->cmd[0], 0, 12);
959 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200960 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100961 srb->cmd[4] = 36;
962 srb->datalen = 36;
963 srb->cmdlen = 12;
964 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530965 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100966 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000967 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200968 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000969
Michael Trimarchi956a4352008-12-10 15:52:06 +0100970 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000971 printf("error in inquiry\n");
972 return -1;
973 }
974 return 0;
975}
976
Michael Trimarchi956a4352008-12-10 15:52:06 +0100977static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000978{
979 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000980
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 ptr = (char *)srb->pdata;
982 memset(&srb->cmd[0], 0, 12);
983 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200984 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100985 srb->cmd[4] = 18;
986 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200987 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 srb->cmdlen = 12;
989 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530990 debug("Request Sense returned %02X %02X %02X\n",
991 srb->sense_buf[2], srb->sense_buf[12],
992 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100993 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000994 return 0;
995}
996
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000998{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200999 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001000
wdenkaffae2b2002-08-17 09:36:01 +00001001 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001005 srb->datalen = 0;
1006 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001007 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1008 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001009 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001010 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001011 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001012 /*
1013 * Check the Key Code Qualifier, if it matches
1014 * "Not Ready - medium not present"
1015 * (the sense Key equals 0x2 and the ASC is 0x3a)
1016 * return immediately as the medium being absent won't change
1017 * unless there is a user action.
1018 */
1019 if ((srb->sense_buf[2] == 0x02) &&
1020 (srb->sense_buf[12] == 0x3a))
1021 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001022 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001023 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001024
wdenkaffae2b2002-08-17 09:36:01 +00001025 return -1;
1026}
1027
Michael Trimarchi956a4352008-12-10 15:52:06 +01001028static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001029{
1030 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031 /* XXX retries */
1032 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001033 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001034 memset(&srb->cmd[0], 0, 12);
1035 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001036 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001037 srb->datalen = 8;
1038 srb->cmdlen = 12;
1039 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001040 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001041 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001042
wdenkaffae2b2002-08-17 09:36:01 +00001043 return -1;
1044}
1045
Michael Trimarchi956a4352008-12-10 15:52:06 +01001046static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
1047 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001048{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049 memset(&srb->cmd[0], 0, 12);
1050 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001051 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001052 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1053 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1054 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1055 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1056 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1057 srb->cmd[8] = (unsigned char) blocks & 0xff;
1058 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301059 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001060 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001061}
1062
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301063static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1064 unsigned short blocks)
1065{
1066 memset(&srb->cmd[0], 0, 12);
1067 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001068 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301069 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1070 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1071 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1072 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1073 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1074 srb->cmd[8] = (unsigned char) blocks & 0xff;
1075 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301076 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301077 return ss->transport(srb, ss);
1078}
1079
wdenkaffae2b2002-08-17 09:36:01 +00001080
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001081#ifdef CONFIG_USB_BIN_FIXUP
1082/*
1083 * Some USB storage devices queried for SCSI identification data respond with
1084 * binary strings, which if output to the console freeze the terminal. The
1085 * workaround is to modify the vendor and product strings read from such
1086 * device with proper values (as reported by 'usb info').
1087 *
1088 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001089 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001090 */
1091static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1092 unsigned char vendor[],
1093 unsigned char product[]) {
1094 const unsigned char max_vendor_len = 40;
1095 const unsigned char max_product_len = 20;
1096 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001097 strncpy((char *)vendor, "SMSC", max_vendor_len);
1098 strncpy((char *)product, "Flash Media Cntrller",
1099 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001100 }
1101}
1102#endif /* CONFIG_USB_BIN_FIXUP */
1103
Simon Glass01f5be92016-02-29 15:25:58 -07001104#ifdef CONFIG_BLK
1105static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1106 lbaint_t blkcnt, void *buffer)
1107#else
Simon Glasse3394752016-02-29 15:25:34 -07001108static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001109 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001110#endif
wdenkaffae2b2002-08-17 09:36:01 +00001111{
Gabe Black7d077682012-10-12 14:26:07 +00001112 lbaint_t start, blks;
1113 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001114 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001115 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001116 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001117 int retry;
wdenk0e2874cb2004-03-02 14:05:39 +00001118 ccb *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001119#ifdef CONFIG_BLK
1120 struct blk_desc *block_dev;
1121#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001122
1123 if (blkcnt == 0)
1124 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001125 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001126#ifdef CONFIG_BLK
1127 block_dev = dev_get_uclass_platdata(dev);
1128 udev = dev_get_parent_priv(dev_get_parent(dev));
1129 debug("\nusb_read: udev %d\n", block_dev->devnum);
1130#else
Simon Glass99e598e2016-02-29 15:25:54 -07001131 debug("\nusb_read: udev %d\n", block_dev->devnum);
1132 udev = usb_dev_desc[block_dev->devnum].priv;
1133 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001134 debug("%s: No device\n", __func__);
1135 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001136 }
Simon Glass01f5be92016-02-29 15:25:58 -07001137#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001138 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001139
1140 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass99e598e2016-02-29 15:25:54 -07001141 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001142 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001143 start = blknr;
1144 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001145
Simon Glass99e598e2016-02-29 15:25:54 -07001146 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1147 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001148
wdenkaffae2b2002-08-17 09:36:01 +00001149 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001150 /* XXX need some comment here */
1151 retry = 2;
1152 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001153 if (blks > USB_MAX_XFER_BLK)
1154 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001155 else
1156 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001157retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001158 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001159 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001160 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001161 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001162 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301163 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001164 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001165 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001166 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001167 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001168 break;
1169 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001170 start += smallblks;
1171 blks -= smallblks;
1172 buf_addr += srb->datalen;
1173 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001174 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001175
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301176 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001177 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301178 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001179
wdenkaffae2b2002-08-17 09:36:01 +00001180 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001181 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001182 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001183 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001184}
1185
Simon Glass01f5be92016-02-29 15:25:58 -07001186#ifdef CONFIG_BLK
1187static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1188 lbaint_t blkcnt, const void *buffer)
1189#else
Simon Glasse3394752016-02-29 15:25:34 -07001190static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001191 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001192#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301193{
Gabe Black7d077682012-10-12 14:26:07 +00001194 lbaint_t start, blks;
1195 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301196 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001197 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001198 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001199 int retry;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301200 ccb *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001201#ifdef CONFIG_BLK
1202 struct blk_desc *block_dev;
1203#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301204
1205 if (blkcnt == 0)
1206 return 0;
1207
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301208 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001209#ifdef CONFIG_BLK
1210 block_dev = dev_get_uclass_platdata(dev);
1211 udev = dev_get_parent_priv(dev_get_parent(dev));
1212 debug("\nusb_read: udev %d\n", block_dev->devnum);
1213#else
Simon Glass99e598e2016-02-29 15:25:54 -07001214 debug("\nusb_read: udev %d\n", block_dev->devnum);
1215 udev = usb_dev_desc[block_dev->devnum].priv;
1216 if (!udev) {
1217 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001218 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001219 }
Simon Glass01f5be92016-02-29 15:25:58 -07001220#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001221 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301222
1223 usb_disable_asynch(1); /* asynch transfer not allowed */
1224
Simon Glass99e598e2016-02-29 15:25:54 -07001225 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001226 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301227 start = blknr;
1228 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301229
Simon Glass99e598e2016-02-29 15:25:54 -07001230 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1231 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301232
1233 do {
1234 /* If write fails retry for max retry count else
1235 * return with number of blocks written successfully.
1236 */
1237 retry = 2;
1238 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001239 if (blks > USB_MAX_XFER_BLK)
1240 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301241 else
1242 smallblks = (unsigned short) blks;
1243retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001244 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301245 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001246 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301247 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001248 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301249 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001250 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301251 if (retry--)
1252 goto retry_it;
1253 blkcnt -= blks;
1254 break;
1255 }
1256 start += smallblks;
1257 blks -= smallblks;
1258 buf_addr += srb->datalen;
1259 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001260 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301261
Simon Glassb43f7682014-10-15 04:38:38 -06001262 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1263 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301264
1265 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001266 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001267 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301268 return blkcnt;
1269
1270}
wdenkaffae2b2002-08-17 09:36:01 +00001271
1272/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001273int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1274 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001275{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001276 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001277 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301278 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001279 unsigned int flags = 0;
1280
wdenkaffae2b2002-08-17 09:36:01 +00001281 /* let's examine the device now */
1282 iface = &dev->config.if_desc[ifnum];
1283
wdenkaffae2b2002-08-17 09:36:01 +00001284 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001285 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1286 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1287 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001288 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001289 /* if it's not a mass storage, we go no further */
1290 return 0;
1291 }
1292
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001293 memset(ss, 0, sizeof(struct us_data));
1294
wdenkaffae2b2002-08-17 09:36:01 +00001295 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301296 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001297
1298 /* Initialize the us_data structure with some useful info */
1299 ss->flags = flags;
1300 ss->ifnum = ifnum;
1301 ss->pusb_dev = dev;
1302 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001303 ss->subclass = iface->desc.bInterfaceSubClass;
1304 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001305
1306 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301307 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001308 switch (ss->protocol) {
1309 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301310 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001311 ss->transport = usb_stor_CB_transport;
1312 ss->transport_reset = usb_stor_CB_reset;
1313 break;
1314
1315 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301316 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001317 ss->transport = usb_stor_CB_transport;
1318 ss->transport_reset = usb_stor_CB_reset;
1319 break;
wdenkde887eb2003-09-10 18:20:28 +00001320 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301321 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001322 ss->transport = usb_stor_BBB_transport;
1323 ss->transport_reset = usb_stor_BBB_reset;
1324 break;
wdenkaffae2b2002-08-17 09:36:01 +00001325 default:
wdenk5f495752004-02-26 23:46:20 +00001326 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001327 return 0;
1328 break;
1329 }
1330
1331 /*
1332 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1333 * An optional interrupt is OK (necessary for CBI protocol).
1334 * We will ignore any others.
1335 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001336 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301337 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001338 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301339 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001340 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301341 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1342 ss->ep_in = ep_desc->bEndpointAddress &
1343 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001344 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001345 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301346 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001347 USB_ENDPOINT_NUMBER_MASK;
1348 }
1349
1350 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301351 if ((ep_desc->bmAttributes &
1352 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1353 ss->ep_int = ep_desc->bEndpointAddress &
1354 USB_ENDPOINT_NUMBER_MASK;
1355 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001356 }
1357 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301358 debug("Endpoints In %d Out %d Int %d\n",
1359 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001360
1361 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001362 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001363 !ss->ep_in || !ss->ep_out ||
1364 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301365 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001366 return 0;
1367 }
1368 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001369 /* We only handle certain protocols. Currently, these are
1370 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001371 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001372 */
wdenk5f495752004-02-26 23:46:20 +00001373 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1374 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001375 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001376 return 0;
1377 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001378 if (ss->ep_int) {
1379 /* we had found an interrupt endpoint, prepare irq pipe
1380 * set up the IRQ pipe and handler
1381 */
wdenkaffae2b2002-08-17 09:36:01 +00001382 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1383 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1384 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001385 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001386 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001387 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001388 return 1;
1389}
1390
Michael Trimarchi956a4352008-12-10 15:52:06 +01001391int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001392 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001393{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001394 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001395 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1396 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1397 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001398 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001399
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001400 pccb->pdata = usb_stor_buf;
1401
1402 dev_desc->target = dev->devnum;
1403 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301404 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001405
Simon Glass78330d62015-03-25 12:22:12 -06001406 if (usb_inquiry(pccb, ss)) {
1407 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001408 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001409 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001410
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001411 perq = usb_stor_buf[0];
1412 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001413
Soeren Moche4828002014-11-08 07:02:14 +01001414 /*
1415 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1416 * they would not respond to test_unit_ready .
1417 */
1418 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001419 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001420 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001421 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001422 if ((modi&0x80) == 0x80) {
1423 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001424 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001425 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001426 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1427 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1428 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001429 dev_desc->vendor[8] = 0;
1430 dev_desc->product[16] = 0;
1431 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001432#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001433 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1434 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001435#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301436 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1437 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001438 if (usb_test_unit_ready(pccb, ss)) {
1439 printf("Device NOT ready\n"
1440 " Request Sense returned %02X %02X %02X\n",
1441 pccb->sense_buf[2], pccb->sense_buf[12],
1442 pccb->sense_buf[13]);
1443 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001444 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001445 return 1;
1446 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001447 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001449 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001450 memset(pccb->pdata, 0, 8);
1451 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001452 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001453 cap[0] = 2880;
1454 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001455 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001456 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001457 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001458#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001459 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1460 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001461
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001462 cap[0] = cpu_to_be32(cap[0]);
1463 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001464#endif
1465
1466 capacity = be32_to_cpu(cap[0]) + 1;
1467 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001468
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001469 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1470 dev_desc->lba = capacity;
1471 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001472 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001473 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301474 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001475
wdenkaffae2b2002-08-17 09:36:01 +00001476 return 1;
1477}
Simon Glassac9774e2015-03-25 12:22:16 -06001478
1479#ifdef CONFIG_DM_USB
1480
1481static int usb_mass_storage_probe(struct udevice *dev)
1482{
Simon Glassde44acf2015-09-28 23:32:01 -06001483 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001484 int ret;
1485
1486 usb_disable_asynch(1); /* asynch transfer not allowed */
1487 ret = usb_stor_probe_device(udev);
1488 usb_disable_asynch(0); /* asynch transfer allowed */
1489
1490 return ret;
1491}
1492
1493static const struct udevice_id usb_mass_storage_ids[] = {
1494 { .compatible = "usb-mass-storage" },
1495 { }
1496};
1497
1498U_BOOT_DRIVER(usb_mass_storage) = {
1499 .name = "usb_mass_storage",
1500 .id = UCLASS_MASS_STORAGE,
1501 .of_match = usb_mass_storage_ids,
1502 .probe = usb_mass_storage_probe,
Simon Glass01f5be92016-02-29 15:25:58 -07001503#ifdef CONFIG_BLK
1504 .platdata_auto_alloc_size = sizeof(struct us_data),
1505#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001506};
1507
1508UCLASS_DRIVER(usb_mass_storage) = {
1509 .id = UCLASS_MASS_STORAGE,
1510 .name = "usb_mass_storage",
1511};
1512
1513static const struct usb_device_id mass_storage_id_table[] = {
1514 {
1515 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1516 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1517 },
1518 { } /* Terminating entry */
1519};
1520
Simon Glass46952fb2015-07-06 16:47:51 -06001521U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001522#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001523
Simon Glass01f5be92016-02-29 15:25:58 -07001524#ifdef CONFIG_BLK
1525static const struct blk_ops usb_storage_ops = {
1526 .read = usb_stor_read,
1527 .write = usb_stor_write,
1528};
1529
1530U_BOOT_DRIVER(usb_storage_blk) = {
1531 .name = "usb_storage_blk",
1532 .id = UCLASS_BLK,
1533 .ops = &usb_storage_ops,
1534};
Simon Glassd3171412016-05-01 11:36:06 -06001535#else
1536U_BOOT_LEGACY_BLK(usb) = {
1537 .if_typename = "usb",
1538 .if_type = IF_TYPE_USB,
1539 .max_devs = USB_MAX_STOR_DEV,
1540 .desc = usb_dev_desc,
1541};
Simon Glassac9774e2015-03-25 12:22:16 -06001542#endif