blob: b524a15e2bf93714c9ea758046d6c651decc4723 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-08-04 01:14:12 +02002 * Most of this source has been derived from the Linux USB
3 * project:
4 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
5 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
6 * (c) 1999 Michael Gee (michael@linuxspecific.com)
7 * (c) 2000 Yggdrasil Computing, Inc.
8 *
9 *
10 * Adapted for U-Boot:
11 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
Simon Glassacf277a2015-03-25 12:22:16 -060012 * Driver model conversion:
13 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000014 *
wdenk149dded2003-09-10 18:20:28 +000015 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020016 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000017 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020018 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000019 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000020 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020021 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +000022 */
23
24/* Note:
25 * Currently only the CBI transport protocoll has been implemented, and it
26 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
27 * transport protocoll may work as well.
28 */
wdenk149dded2003-09-10 18:20:28 +000029/*
30 * New Note:
31 * Support for USB Mass Storage Devices (BBB) has been added. It has
32 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000033 */
wdenkaffae2b2002-08-17 09:36:01 +000034
35
wdenkaffae2b2002-08-17 09:36:01 +000036#include <common.h>
37#include <command.h>
Simon Glassacf277a2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glass91557572015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass4fd074d2014-10-15 04:38:38 -060040#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glasscf92e052015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggersc9182612008-05-21 22:12:00 +020043#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
Simon Glass07b2b782016-02-29 15:25:58 -070046#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000047
Grant Likely735dd972007-02-20 09:04:34 +010048#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000049#include <usb.h>
50
wdenk80885a92004-02-26 23:46:20 +000051#undef BBB_COMDAT_TRACE
52#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000053
wdenkaffae2b2002-08-17 09:36:01 +000054#include <scsi.h>
55/* direction table -- this indicates the direction of the data
56 * transfer for each command code -- a 1 indicates input
57 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040058static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000059 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
60 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
63};
64#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
65
Puneet Saxenaf5766132012-04-03 14:56:06 +053066static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010067static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000068
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
Simon Glass07b2b782016-02-29 15:25:58 -070071#ifndef CONFIG_BLK
Simon Glass4101f682016-02-29 15:25:34 -070072static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -070073#endif
wdenkaffae2b2002-08-17 09:36:01 +000074
75struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010076typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
77typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000078
79struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010080 struct usb_device *pusb_dev; /* this usb_device */
81
82 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020083# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010084 unsigned char ifnum; /* interface number */
85 unsigned char ep_in; /* in endpoint */
86 unsigned char ep_out; /* out ....... */
87 unsigned char ep_int; /* interrupt . */
88 unsigned char subclass; /* as in overview */
89 unsigned char protocol; /* .............. */
90 unsigned char attention_done; /* force attn on first cmd */
91 unsigned short ip_data; /* interrupt data */
92 int action; /* what to do */
93 int ip_wanted; /* needed */
94 int *irq_handle; /* for USB int requests */
95 unsigned int irqpipe; /* pipe for release_irq */
96 unsigned char irqmaxp; /* max packed for irq Pipe */
97 unsigned char irqinterval; /* Intervall for IRQ Pipe */
98 ccb *srb; /* current srb */
99 trans_reset transport_reset; /* reset routine */
100 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000101};
102
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200103#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000104/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200105 * The U-Boot EHCI driver can handle any transfer length as long as there is
106 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
107 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000108 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200109#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200110#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200111#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200112#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000113
Simon Glass07b2b782016-02-29 15:25:58 -0700114#ifndef CONFIG_BLK
wdenkaffae2b2002-08-17 09:36:01 +0000115static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -0700116#endif
wdenkaffae2b2002-08-17 09:36:01 +0000117
wdenk80885a92004-02-26 23:46:20 +0000118#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000119#define USB_STOR_TRANSPORT_FAILED -1
120#define USB_STOR_TRANSPORT_ERROR -2
121
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100122int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glass4101f682016-02-29 15:25:34 -0700123 struct blk_desc *dev_desc);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100124int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
125 struct us_data *ss);
Simon Glass07b2b782016-02-29 15:25:58 -0700126#ifdef CONFIG_BLK
127static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
128 lbaint_t blkcnt, void *buffer);
129static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
130 lbaint_t blkcnt, const void *buffer);
131#else
Simon Glass4101f682016-02-29 15:25:34 -0700132static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700133 lbaint_t blkcnt, void *buffer);
Simon Glass4101f682016-02-29 15:25:34 -0700134static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700135 lbaint_t blkcnt, const void *buffer);
Simon Glass07b2b782016-02-29 15:25:58 -0700136#endif
wdenkaffae2b2002-08-17 09:36:01 +0000137void uhci_show_temp_int_td(void);
138
Kim Phillips199adb62012-10-29 13:34:32 +0000139static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000140{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200141 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000142}
143
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100144/*******************************************************************************
Wolfgang Denk9c998aa2005-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 Vaichasf6b44e02008-03-25 12:09:07 +1100148int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200149{
Simon Glass9807c3b2016-02-29 15:25:54 -0700150 int count = 0;
Simon Glass07b2b782016-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 Denk9c998aa2005-07-21 11:57:57 +0200164 int i;
165
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100166 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200167 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100168 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200169 dev_print(&usb_dev_desc[i]);
170 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100171 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100172 }
Simon Glass07b2b782016-02-29 15:25:58 -0700173#endif
Simon Glass9807c3b2016-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 Glassb94fc852016-03-16 07:45:44 -0600179 return 0;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200180}
181
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200182static unsigned int usb_get_max_lun(struct us_data *us)
183{
184 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530185 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-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 Saxenaf5766132012-04-03 14:56:06 +0530191 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200192 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530193 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530194 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200195}
196
Simon Glass9807c3b2016-02-29 15:25:54 -0700197static int usb_stor_probe_device(struct usb_device *udev)
Simon Glass91557572015-03-25 12:22:15 -0600198{
Simon Glass9807c3b2016-02-29 15:25:54 -0700199 int lun, max_lun;
Simon Glass07b2b782016-02-29 15:25:58 -0700200
201#ifdef CONFIG_BLK
202 struct us_data *data;
Simon Glass07b2b782016-02-29 15:25:58 -0700203 int ret;
204#else
Simon Glass9807c3b2016-02-29 15:25:54 -0700205 int start;
206
207 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600208 return -ENOENT; /* no more devices available */
Simon Glass07b2b782016-02-29 15:25:58 -0700209#endif
Simon Glass91557572015-03-25 12:22:15 -0600210
Simon Glass07b2b782016-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 Glass9107c972016-05-01 11:36:29 -0600225 char str[10];
Simon Glass07b2b782016-02-29 15:25:58 -0700226
Simon Glass9107c972016-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 Glass07b2b782016-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 Glassc89e79d2016-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 Glass9807c3b2016-02-29 15:25:54 -0700261 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
262 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600263
Simon Glass9807c3b2016-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 Glass91557572015-03-25 12:22:15 -0600269
Simon Glass9807c3b2016-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 Glass91557572015-03-25 12:22:15 -0600274
Simon Glass9807c3b2016-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 Glass07b2b782016-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 Glass9807c3b2016-02-29 15:25:54 -0700292 usb_max_devs++;
293 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600294 }
295 }
Simon Glass07b2b782016-02-29 15:25:58 -0700296#endif
Simon Glass91557572015-03-25 12:22:15 -0600297
Simon Glass91557572015-03-25 12:22:15 -0600298 return 0;
299}
300
301void usb_stor_reset(void)
302{
303 usb_max_devs = 0;
304}
305
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100306/*******************************************************************************
Wolfgang Denk9c998aa2005-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100313 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200314 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100315
Michal Simekb9847002016-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 Glass91557572015-03-25 12:22:15 -0600321 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100322 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600323 struct usb_device *dev;
324
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100325 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530326 debug("i=%d\n", i);
Simon Glass91557572015-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 Denk095b8a32005-08-02 17:06:17 +0200330
wdenkaffae2b2002-08-17 09:36:01 +0000331 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekb9847002016-12-21 09:35:08 +0100332#endif
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200333 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100334 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000335 return 0;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100342 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000343
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-04-12 16:34:33 +0530350#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000351
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100352static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000353{
354 int i;
Michael Trimarchia0cb3fc2008-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 Glass05108132015-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100406 this_xfer, &partial,
407 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530408 debug("bulk_msg returned %d xferred %d/%d\n",
409 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100422 us->pusb_dev->status = stat;
423 if (this_xfer == partial) {
Vivek Gautamceb49722013-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 Gautamceb49722013-04-12 16:34:33 +0530434 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000435 return result;
436 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530437 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100438 if (this_xfer == partial) {
Vivek Gautamceb49722013-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-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
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530479 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-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 Phillips199adb62012-10-29 13:34:32 +0000483 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200484
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100485 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530486 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000487 return -1;
488 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200489
wdenk149dded2003-09-10 18:20:28 +0000490 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX reset\n",
493 result, us->pusb_dev->status);
wdenk149dded2003-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 Frysinger5b84dd62012-03-05 13:47:00 +0000497 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530498 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
499 result, us->pusb_dev->status);
wdenk149dded2003-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 Frysinger5b84dd62012-03-05 13:47:00 +0000503 mdelay(150);
Vivek Gautamceb49722013-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");
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530519 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 Frysinger5b84dd62012-03-05 13:47:00 +0000530 mdelay(1500);
Vivek Gautamceb49722013-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 Gautamceb49722013-04-12 16:34:33 +0530536 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000537 return 0;
538}
539
wdenk149dded2003-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 Phillips199adb62012-10-29 13:34:32 +0000544static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000545{
546 int result;
547 int actlen;
548 int dir_in;
549 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600550 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000551
552 dir_in = US_DIRECTION(srb->cmd[0]);
553
554#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530555 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100556 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
557 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000558 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100559 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530566 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-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 Saxenaf5766132012-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;
wdenk149dded2003-09-10 18:20:28 +0000579 /* copy the command data into the CBW command data buffer */
580 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300581
Puneet Saxenaf5766132012-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100584 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000585 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530586 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-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 Phillips199adb62012-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 Denk77ddac92005-10-13 16:45:02 +0200595 int result = 0;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100600 retry = 5;
601 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000602
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100619 srb->cmd, srb->cmdlen,
620 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100625 if (us->pusb_dev->status & USB_ST_STALLED) {
626 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530627 debug(" stall during command found," \
628 " clear pipe\n");
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100644 result = us_one_transfer(us, pipe, (char *)srb->pdata,
645 srb->datalen);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Phillips199adb62012-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
wdenk80885a92004-02-26 23:46:20 +0000666 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100667 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000668 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
669 timeout = 1000;
670 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300671 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000672 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000673 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000674 }
675 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-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 Cascadiana6f70a32016-03-15 12:16:39 -0700680 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamceb49722013-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 */
wdenk80885a92004-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
wdenk80885a92004-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) {
wdenk80885a92004-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
wdenk149dded2003-09-10 18:20:28 +0000708/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000709static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000710{
wdenk149dded2003-09-10 18:20:28 +0000711 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada8319aeb2016-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);
wdenk149dded2003-09-10 18:20:28 +0000715}
716
Kim Phillips199adb62012-10-29 13:34:32 +0000717static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-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 Glass2e17c872015-03-25 12:22:11 -0600723 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530732 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000733 result = usb_stor_BBB_comdat(srb, us);
734 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530735 debug("failed to send CBW status %ld\n",
736 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000737 usb_stor_BBB_reset(us);
738 return USB_STOR_TRANSPORT_FAILED;
739 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200740 if (!(us->flags & USB_READY))
741 mdelay(5);
wdenk149dded2003-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 */
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530749 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000750 if (dir_in)
751 pipe = pipein;
752 else
753 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300754
Michael Trimarchia0cb3fc2008-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);
wdenk149dded2003-09-10 18:20:28 +0000757 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100758 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530759 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000760 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100761 result = usb_stor_BBB_clear_endpt_stall(us,
762 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000763 if (result >= 0)
764 /* continue on to STATUS phase */
765 goto st;
766 }
767 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530768 debug("usb_bulk_msg error status %ld\n",
769 us->pusb_dev->status);
wdenk149dded2003-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100779st:
wdenk149dded2003-09-10 18:20:28 +0000780 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100781again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530782 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530783 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200784 &actlen, USB_CNTL_TIMEOUT*5);
785
wdenk149dded2003-09-10 18:20:28 +0000786 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100787 if ((result < 0) && (retry < 1) &&
788 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530789 debug("STATUS:stall\n");
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530797 debug("usb_bulk_msg error status %ld\n",
798 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000799 usb_stor_BBB_reset(us);
800 return USB_STOR_TRANSPORT_FAILED;
801 }
802#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530803 ptr = (unsigned char *)csw;
wdenk149dded2003-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 Saxenaf5766132012-04-03 14:56:06 +0530809 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000810 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
811 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530812 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530813 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000814 usb_stor_BBB_reset(us);
815 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530816 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530817 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000818 usb_stor_BBB_reset(us);
819 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530820 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530821 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000822 usb_stor_BBB_reset(us);
823 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530824 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530825 debug("=PHASE\n");
wdenk149dded2003-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 Gautamceb49722013-04-12 16:34:33 +0530829 debug("transferred %dB instead of %ldB\n",
830 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000831 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530832 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530833 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000834 return USB_STOR_TRANSPORT_FAILED;
835 }
836
837 return result;
838}
839
Kim Phillips199adb62012-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100842 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000843 ccb *psrb;
844 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000846
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200847 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100860 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530861 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000862 return status;
863 }
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100876 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Denkd0ff51b2008-07-14 15:19:07 +0200894 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100895 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000896 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100897 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Gautamceb49722013-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 Gautamceb49722013-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100917 }
918
wdenkaffae2b2002-08-17 09:36:01 +0000919 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100920 switch (srb->sense_buf[2]) {
921 case 0x01:
922 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000923 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000924 break;
Michael Trimarchia0cb3fc2008-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]);
wdenk149dded2003-09-10 18:20:28 +0000932 return USB_STOR_TRANSPORT_FAILED;
933 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000934 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000935 goto do_retry;
936 }
937 break;
938 default:
Michael Trimarchia0cb3fc2008-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]);
wdenk149dded2003-09-10 18:20:28 +0000944 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100945 } else
wdenk149dded2003-09-10 18:20:28 +0000946 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000947 break;
wdenkaffae2b2002-08-17 09:36:01 +0000948 }
949 return USB_STOR_TRANSPORT_FAILED;
950}
951
952
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100953static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000954{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955 int retry, i;
956 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000957 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 memset(&srb->cmd[0], 0, 12);
959 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200960 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-04-12 16:34:33 +0530965 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100966 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000967 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200968 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000969
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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;
wdenk80885a92004-02-26 23:46:20 +0000980
Michael Trimarchia0cb3fc2008-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ès99e9ed12010-10-05 22:04:26 +0200984 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100985 srb->cmd[4] = 18;
986 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200987 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100988 srb->cmdlen = 12;
989 ss->transport(srb, ss);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100993 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000994 return 0;
995}
996
Michael Trimarchia0cb3fc2008-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 Denk9c998aa2005-07-21 11:57:57 +0200999 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001000
wdenkaffae2b2002-08-17 09:36:01 +00001001 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001005 srb->datalen = 0;
1006 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-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ébaudeau3e8581b2012-08-10 18:27:11 +02001010 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001011 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-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 Frysinger5b84dd62012-03-05 13:47:00 +00001022 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001023 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001024
wdenkaffae2b2002-08-17 09:36:01 +00001025 return -1;
1026}
1027
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001031 /* XXX retries */
1032 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001033 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001034 memset(&srb->cmd[0], 0, 12);
1035 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001036 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001041 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001042
wdenkaffae2b2002-08-17 09:36:01 +00001043 return -1;
1044}
1045
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001049 memset(&srb->cmd[0], 0, 12);
1050 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001051 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-04-12 16:34:33 +05301059 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001060 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001061}
1062
Mahavir Jain127e1082009-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ès99e9ed12010-10-05 22:04:26 +02001068 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-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 Gautamceb49722013-04-12 16:34:33 +05301076 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301077 return ss->transport(srb, ss);
1078}
1079
wdenkaffae2b2002-08-17 09:36:01 +00001080
Bartlomiej Siekaddde6b72006-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 Glass4101f682016-02-29 15:25:34 -07001089 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-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 Trimarchia0cb3fc2008-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 Siekaddde6b72006-08-22 10:38:18 +02001100 }
1101}
1102#endif /* CONFIG_USB_BIN_FIXUP */
1103
Simon Glass07b2b782016-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 Glass4101f682016-02-29 15:25:34 -07001108static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001109 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001110#endif
wdenkaffae2b2002-08-17 09:36:01 +00001111{
Gabe Blacke81e79e2012-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 Glass9807c3b2016-02-29 15:25:54 -07001115 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001116 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001117 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001118 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001119#ifdef CONFIG_BLK
1120 struct blk_desc *block_dev;
1121#endif
wdenkf8d813e2004-03-02 14:05:39 +00001122
1123 if (blkcnt == 0)
1124 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001125 /* Setup device */
Simon Glass07b2b782016-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 Glass9807c3b2016-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 Glass84073b62015-03-25 12:22:13 -06001134 debug("%s: No device\n", __func__);
1135 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001136 }
Simon Glass07b2b782016-02-29 15:25:58 -07001137#endif
Simon Glass9807c3b2016-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 Glass9807c3b2016-02-29 15:25:54 -07001141 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001142 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001143 start = blknr;
1144 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001145
Simon Glass9807c3b2016-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001148
wdenkaffae2b2002-08-17 09:36:01 +00001149 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001150 /* XXX need some comment here */
1151 retry = 2;
1152 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001153 if (blks > USB_MAX_XFER_BLK)
1154 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001155 else
1156 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001157retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001158 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001159 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001160 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001161 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001162 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301163 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001164 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001165 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001166 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001167 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001168 break;
1169 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001170 start += smallblks;
1171 blks -= smallblks;
1172 buf_addr += srb->datalen;
1173 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001174 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001175
Vivek Gautamceb49722013-04-12 16:34:33 +05301176 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001177 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301178 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001179
wdenkaffae2b2002-08-17 09:36:01 +00001180 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001181 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001182 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001183 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001184}
1185
Simon Glass07b2b782016-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 Glass4101f682016-02-29 15:25:34 -07001190static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001191 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001192#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301193{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001194 lbaint_t start, blks;
1195 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301196 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001197 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001198 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001199 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301200 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001201#ifdef CONFIG_BLK
1202 struct blk_desc *block_dev;
1203#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301204
1205 if (blkcnt == 0)
1206 return 0;
1207
Mahavir Jain127e1082009-11-03 12:22:10 +05301208 /* Setup device */
Simon Glass07b2b782016-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 Glass9807c3b2016-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 Glass84073b62015-03-25 12:22:13 -06001218 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001219 }
Simon Glass07b2b782016-02-29 15:25:58 -07001220#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001221 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301222
1223 usb_disable_asynch(1); /* asynch transfer not allowed */
1224
Simon Glass9807c3b2016-02-29 15:25:54 -07001225 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001226 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301227 start = blknr;
1228 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301229
Simon Glass9807c3b2016-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 Jain127e1082009-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ébaudeau4bee5c82012-08-10 18:23:25 +02001239 if (blks > USB_MAX_XFER_BLK)
1240 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301241 else
1242 smallblks = (unsigned short) blks;
1243retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001244 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301245 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001246 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301247 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001248 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301249 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001250 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-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ébaudeau3e8581b2012-08-10 18:27:11 +02001260 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301261
Simon Glass4fd074d2014-10-15 04:38:38 -06001262 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1263 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301264
1265 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001266 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001267 debug("\n");
Mahavir Jain127e1082009-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 Trimarchia0cb3fc2008-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 Rix8f8bd562009-10-31 12:37:38 -05001276 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001277 int i;
Vivek Gautam605bd752013-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 Rix8f8bd562009-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 Glass1d5827a2015-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 Denk9c998aa2005-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 Gautamceb49722013-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 Rinif5fb78a2015-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 Gautamceb49722013-04-12 16:34:33 +05301307 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001308 switch (ss->protocol) {
1309 case US_PR_CB:
Vivek Gautamceb49722013-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 Gautamceb49722013-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;
wdenk149dded2003-09-10 18:20:28 +00001320 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301321 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-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:
wdenk80885a92004-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 Rix8f8bd562009-10-31 12:37:38 -05001336 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-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 Gautam605bd752013-04-12 16:34:34 +05301339 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001340 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001345 ss->ep_out =
Vivek Gautam605bd752013-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 Gautam605bd752013-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 Gautamceb49722013-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 Rix8f8bd562009-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 Gautamceb49722013-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 */
wdenk149dded2003-09-10 18:20:28 +00001369 /* We only handle certain protocols. Currently, these are
1370 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001371 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001372 */
wdenk80885a92004-02-26 23:46:20 +00001373 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1374 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001385 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001386 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001387 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001388 return 1;
1389}
1390
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001391int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001392 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001393{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001394 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-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 Denk9c998aa2005-07-21 11:57:57 +02001398 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001399
Wolfgang Denk9c998aa2005-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 Gautamceb49722013-04-12 16:34:33 +05301404 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001405
Simon Glass1d5827a2015-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 Glass1d5827a2015-03-25 12:22:12 -06001409 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001410
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001411 perq = usb_stor_buf[0];
1412 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001413
Soeren Moch6a559bb2014-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 Glass1d5827a2015-03-25 12:22:12 -06001419 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001420 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001421 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001422 if ((modi&0x80) == 0x80) {
1423 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001424 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001425 }
Sergey Temerkhanovf6570872015-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 Denk9c998aa2005-07-21 11:57:57 +02001429 dev_desc->vendor[8] = 0;
1430 dev_desc->product[16] = 0;
1431 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001432#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001433 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1434 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001435#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301436 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1437 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-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 Denk9c998aa2005-07-21 11:57:57 +02001444 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001445 return 1;
1446 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001447 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001449 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-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 Denk9c998aa2005-07-21 11:57:57 +02001453 cap[0] = 2880;
1454 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001455 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001456 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001459 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1460 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001461
Christian Eggersc9182612008-05-21 22:12:00 +02001462 cap[0] = cpu_to_be32(cap[0]);
1463 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001464#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001465
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001466 capacity = be32_to_cpu(cap[0]) + 1;
1467 blksz = be32_to_cpu(cap[1]);
1468
1469 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1470 dev_desc->lba = capacity;
1471 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001472 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001473 dev_desc->type = perq;
Vivek Gautamceb49722013-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 Glassacf277a2015-03-25 12:22:16 -06001478
1479#ifdef CONFIG_DM_USB
1480
1481static int usb_mass_storage_probe(struct udevice *dev)
1482{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001483 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-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 Glass07b2b782016-02-29 15:25:58 -07001503#ifdef CONFIG_BLK
1504 .platdata_auto_alloc_size = sizeof(struct us_data),
1505#endif
Simon Glassacf277a2015-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 Glassabb59cf2015-07-06 16:47:51 -06001521U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001522#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001523
Simon Glass07b2b782016-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 Glassc0543bf2016-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 Glassacf277a2015-03-25 12:22:16 -06001542#endif