blob: f2da3a3cadcd7b687d03390d5927e7444e200d3a [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;
203 char dev_name[30], *str;
204 int ret;
205#else
Simon Glass9807c3b2016-02-29 15:25:54 -0700206 int start;
207
208 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600209 return -ENOENT; /* no more devices available */
Simon Glass07b2b782016-02-29 15:25:58 -0700210#endif
Simon Glass91557572015-03-25 12:22:15 -0600211
Simon Glass07b2b782016-02-29 15:25:58 -0700212 debug("\n\nProbing for storage\n");
213#ifdef CONFIG_BLK
214 /*
215 * We store the us_data in the mass storage device's platdata. It
216 * is shared by all LUNs (block devices) attached to this mass storage
217 * device.
218 */
219 data = dev_get_platdata(udev->dev);
220 if (!usb_storage_probe(udev, 0, data))
221 return 0;
222 max_lun = usb_get_max_lun(data);
223 for (lun = 0; lun <= max_lun; lun++) {
224 struct blk_desc *blkdev;
225 struct udevice *dev;
226
227 snprintf(dev_name, sizeof(dev_name), "%s.lun%d",
228 udev->dev->name, lun);
229 str = strdup(dev_name);
230 if (!str)
231 return -ENOMEM;
232 ret = blk_create_device(udev->dev, "usb_storage_blk", str,
233 IF_TYPE_USB, usb_max_devs, 512, 0, &dev);
234 if (ret) {
235 debug("Cannot bind driver\n");
236 return ret;
237 }
238
239 blkdev = dev_get_uclass_platdata(dev);
240 blkdev->target = 0xff;
241 blkdev->lun = lun;
242
243 ret = usb_stor_get_info(udev, data, blkdev);
244 if (ret == 1)
245 ret = blk_prepare_device(dev);
246 if (!ret) {
247 usb_max_devs++;
248 debug("%s: Found device %p\n", __func__, udev);
249 } else {
250 debug("usb_stor_get_info: Invalid device\n");
251 ret = device_unbind(dev);
252 if (ret)
253 return ret;
254 }
255 }
256#else
Simon Glassc89e79d2016-02-29 15:25:53 -0700257 /* We don't have space to even probe if we hit the maximum */
258 if (usb_max_devs == USB_MAX_STOR_DEV) {
259 printf("max USB Storage Device reached: %d stopping\n",
260 usb_max_devs);
261 return -ENOSPC;
262 }
263
Simon Glass9807c3b2016-02-29 15:25:54 -0700264 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
265 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600266
Simon Glass9807c3b2016-02-29 15:25:54 -0700267 /*
268 * OK, it's a storage device. Iterate over its LUNs and populate
269 * usb_dev_desc'
270 */
271 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600272
Simon Glass9807c3b2016-02-29 15:25:54 -0700273 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
274 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
275 lun++) {
276 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600277
Simon Glass9807c3b2016-02-29 15:25:54 -0700278 blkdev = &usb_dev_desc[usb_max_devs];
279 memset(blkdev, '\0', sizeof(struct blk_desc));
280 blkdev->if_type = IF_TYPE_USB;
281 blkdev->devnum = usb_max_devs;
282 blkdev->part_type = PART_TYPE_UNKNOWN;
283 blkdev->target = 0xff;
284 blkdev->type = DEV_TYPE_UNKNOWN;
285 blkdev->block_read = usb_stor_read;
286 blkdev->block_write = usb_stor_write;
287 blkdev->lun = lun;
288 blkdev->priv = udev;
289
290 if (usb_stor_get_info(udev, &usb_stor[start],
291 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700292 debug("partype: %d\n", blkdev->part_type);
293 part_init(blkdev);
294 debug("partype: %d\n", blkdev->part_type);
Simon Glass9807c3b2016-02-29 15:25:54 -0700295 usb_max_devs++;
296 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600297 }
298 }
Simon Glass07b2b782016-02-29 15:25:58 -0700299#endif
Simon Glass91557572015-03-25 12:22:15 -0600300
Simon Glass91557572015-03-25 12:22:15 -0600301 return 0;
302}
303
304void usb_stor_reset(void)
305{
306 usb_max_devs = 0;
307}
308
Simon Glassacf277a2015-03-25 12:22:16 -0600309#ifndef CONFIG_DM_USB
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100310/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200311 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000312 * to the user if mode = 1
313 * returns current device or -1 if no
314 */
315int usb_stor_scan(int mode)
316{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600317 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000318
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100319 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200320 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100321
wdenkaffae2b2002-08-17 09:36:01 +0000322 usb_disable_asynch(1); /* asynch transfer not allowed */
323
Simon Glass91557572015-03-25 12:22:15 -0600324 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100325 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600326 struct usb_device *dev;
327
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100328 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530329 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600330 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000331 break;
wdenkaffae2b2002-08-17 09:36:01 +0000332 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200333
wdenkaffae2b2002-08-17 09:36:01 +0000334 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200335 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100336 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000337 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100338 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000339}
Simon Glassacf277a2015-03-25 12:22:16 -0600340#endif
wdenkaffae2b2002-08-17 09:36:01 +0000341
342static int usb_stor_irq(struct usb_device *dev)
343{
344 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100345 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000346
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100347 if (us->ip_wanted)
348 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000349 return 0;
350}
351
352
Vivek Gautamceb49722013-04-12 16:34:33 +0530353#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000354
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100355static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000356{
357 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100358 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
359 for (i = 0; i < 12; i++)
360 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000361 printf("\n");
362}
363
364static void display_int_status(unsigned long tmp)
365{
366 printf("Status: %s %s %s %s %s %s %s\n",
367 (tmp & USB_ST_ACTIVE) ? "Active" : "",
368 (tmp & USB_ST_STALLED) ? "Stalled" : "",
369 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
370 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
371 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
372 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
373 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
374}
375#endif
376/***********************************************************************
377 * Data transfer routines
378 ***********************************************************************/
379
380static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
381{
382 int max_size;
383 int this_xfer;
384 int result;
385 int partial;
386 int maxtry;
387 int stat;
388
389 /* determine the maximum packet size for these transfers */
390 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
391
392 /* while we have data left to transfer */
393 while (length) {
394
395 /* calculate how long this will be -- maximum or a remainder */
396 this_xfer = length > max_size ? max_size : length;
397 length -= this_xfer;
398
399 /* setup the retry counter */
400 maxtry = 10;
401
402 /* set up the transfer loop */
403 do {
404 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600405 debug("Bulk xfer 0x%lx(%d) try #%d\n",
406 (ulong)map_to_sysmem(buf), this_xfer,
407 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000408 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100409 this_xfer, &partial,
410 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530411 debug("bulk_msg returned %d xferred %d/%d\n",
412 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100413 if (us->pusb_dev->status != 0) {
414 /* if we stall, we need to clear it before
415 * we go on
416 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530417#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000418 display_int_status(us->pusb_dev->status);
419#endif
420 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530421 debug("stalled ->clearing endpoint" \
422 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000423 stat = us->pusb_dev->status;
424 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100425 us->pusb_dev->status = stat;
426 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530427 debug("bulk transferred" \
428 "with error %lX," \
429 " but data ok\n",
430 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000431 return 0;
432 }
433 else
434 return result;
435 }
436 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530437 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000438 return result;
439 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530440 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100441 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530442 debug(" %ld, but data ok\n",
443 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000444 return 0;
445 }
446 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530447 debug(" %ld, data %d\n",
448 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000449 if (!maxtry--)
450 return result;
451 }
452 /* update to show what data was transferred */
453 this_xfer -= partial;
454 buf += partial;
455 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100456 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000457 }
458
459 /* if we get here, we're done and successful */
460 return 0;
461}
462
wdenk149dded2003-09-10 18:20:28 +0000463static int usb_stor_BBB_reset(struct us_data *us)
464{
465 int result;
466 unsigned int pipe;
467
468 /*
469 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
470 *
471 * For Reset Recovery the host shall issue in the following order:
472 * a) a Bulk-Only Mass Storage Reset
473 * b) a Clear Feature HALT to the Bulk-In endpoint
474 * c) a Clear Feature HALT to the Bulk-Out endpoint
475 *
476 * This is done in 3 steps.
477 *
478 * If the reset doesn't succeed, the device should be port reset.
479 *
480 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
481 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530482 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100483 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
484 US_BBB_RESET,
485 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000486 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200487
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100488 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530489 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000490 return -1;
491 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200492
wdenk149dded2003-09-10 18:20:28 +0000493 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000494 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530495 debug("BBB_reset result %d: status %lX reset\n",
496 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000497 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
498 result = usb_clear_halt(us->pusb_dev, pipe);
499 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000500 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530501 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
502 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000503 /* long wait for reset */
504 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
505 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000506 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530507 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
508 result, us->pusb_dev->status);
509 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000510 return 0;
511}
512
wdenkaffae2b2002-08-17 09:36:01 +0000513/* FIXME: this reset function doesn't really reset the port, and it
514 * should. Actually it should probably do what it's doing here, and
515 * reset the port physically
516 */
517static int usb_stor_CB_reset(struct us_data *us)
518{
519 unsigned char cmd[12];
520 int result;
521
Vivek Gautamceb49722013-04-12 16:34:33 +0530522 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100523 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000524 cmd[0] = SCSI_SEND_DIAG;
525 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100526 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
527 US_CBI_ADSC,
528 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
529 0, us->ifnum, cmd, sizeof(cmd),
530 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000531
532 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000533 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530534 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
535 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000536 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
537 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
538
Vivek Gautamceb49722013-04-12 16:34:33 +0530539 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000540 return 0;
541}
542
wdenk149dded2003-09-10 18:20:28 +0000543/*
544 * Set up the command for a BBB device. Note that the actual SCSI
545 * command is copied into cbw.CBWCDB.
546 */
Kim Phillips199adb62012-10-29 13:34:32 +0000547static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000548{
549 int result;
550 int actlen;
551 int dir_in;
552 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600553 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000554
555 dir_in = US_DIRECTION(srb->cmd[0]);
556
557#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530558 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100559 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
560 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000561 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100562 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000563 printf("cmd[%d] %#x ", result, srb->cmd[result]);
564 printf("\n");
565 }
566#endif
567 /* sanity checks */
568 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530569 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000570 return -1;
571 }
572
573 /* always OUT to the ep */
574 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
575
Puneet Saxenaf5766132012-04-03 14:56:06 +0530576 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
577 cbw->dCBWTag = cpu_to_le32(CBWTag++);
578 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
579 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
580 cbw->bCBWLUN = srb->lun;
581 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000582 /* copy the command data into the CBW command data buffer */
583 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300584
Puneet Saxenaf5766132012-04-03 14:56:06 +0530585 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
586 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100587 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000588 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530589 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000590 return result;
591}
592
wdenkaffae2b2002-08-17 09:36:01 +0000593/* FIXME: we also need a CBI_command which sets up the completion
594 * interrupt, and waits for it
595 */
Kim Phillips199adb62012-10-29 13:34:32 +0000596static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000597{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200598 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100599 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000600 unsigned int pipe;
601 unsigned long status;
602
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100603 retry = 5;
604 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000605
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100606 if (dir_in)
607 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
608 else
609 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
610
611 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530612 debug("CBI gets a command: Try %d\n", 5 - retry);
613#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000614 usb_show_srb(srb);
615#endif
616 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100617 result = usb_control_msg(us->pusb_dev,
618 usb_sndctrlpipe(us->pusb_dev , 0),
619 US_CBI_ADSC,
620 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000621 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100622 srb->cmd, srb->cmdlen,
623 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530624 debug("CB_transport: control msg returned %d, status %lX\n",
625 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000626 /* check the return code for the command */
627 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100628 if (us->pusb_dev->status & USB_ST_STALLED) {
629 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530630 debug(" stall during command found," \
631 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100632 usb_clear_halt(us->pusb_dev,
633 usb_sndctrlpipe(us->pusb_dev, 0));
634 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000635 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530636 debug(" error during command %02X" \
637 " Stat = %lX\n", srb->cmd[0],
638 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000639 return result;
640 }
641 /* transfer the data payload for this command, if one exists*/
642
Vivek Gautamceb49722013-04-12 16:34:33 +0530643 debug("CB_transport: control msg returned %d," \
644 " direction is %s to go 0x%lx\n", result,
645 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000646 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100647 result = us_one_transfer(us, pipe, (char *)srb->pdata,
648 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530649 debug("CBI attempted to transfer data," \
650 " result is %d status %lX, len %d\n",
651 result, us->pusb_dev->status,
652 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100653 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000654 break;
655 } /* if (srb->datalen) */
656 else
657 break;
658 }
659 /* return result */
660
661 return result;
662}
663
664
Kim Phillips199adb62012-10-29 13:34:32 +0000665static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000666{
667 int timeout;
668
wdenk80885a92004-02-26 23:46:20 +0000669 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100670 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000671 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
672 timeout = 1000;
673 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300674 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000675 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000676 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000677 }
678 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100679 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000680 us->ip_wanted = 0;
681 return USB_STOR_TRANSPORT_ERROR;
682 }
Vagrant Cascadiana6f70a32016-03-15 12:16:39 -0700683 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamceb49722013-04-12 16:34:33 +0530684 us->ip_data, us->pusb_dev->irq_act_len,
685 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000686 /* UFI gives us ASC and ASCQ, like a request sense */
687 if (us->subclass == US_SC_UFI) {
688 if (srb->cmd[0] == SCSI_REQ_SENSE ||
689 srb->cmd[0] == SCSI_INQUIRY)
690 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000691 else if (us->ip_data)
692 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000693 else
wdenk80885a92004-02-26 23:46:20 +0000694 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000695 }
696 /* otherwise, we interpret the data normally */
697 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000698 case 0x0001:
699 return USB_STOR_TRANSPORT_GOOD;
700 case 0x0002:
701 return USB_STOR_TRANSPORT_FAILED;
702 default:
703 return USB_STOR_TRANSPORT_ERROR;
704 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000705 return USB_STOR_TRANSPORT_ERROR;
706}
707
708#define USB_TRANSPORT_UNKNOWN_RETRY 5
709#define USB_TRANSPORT_NOT_READY_RETRY 10
710
wdenk149dded2003-09-10 18:20:28 +0000711/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000712static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000713{
714 int result;
715
716 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100717 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000718 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000719 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000720 return result;
721}
722
Kim Phillips199adb62012-10-29 13:34:32 +0000723static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000724{
725 int result, retry;
726 int dir_in;
727 int actlen, data_actlen;
728 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600729 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000730#ifdef BBB_XPORT_TRACE
731 unsigned char *ptr;
732 int index;
733#endif
734
735 dir_in = US_DIRECTION(srb->cmd[0]);
736
737 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530738 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000739 result = usb_stor_BBB_comdat(srb, us);
740 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530741 debug("failed to send CBW status %ld\n",
742 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000743 usb_stor_BBB_reset(us);
744 return USB_STOR_TRANSPORT_FAILED;
745 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200746 if (!(us->flags & USB_READY))
747 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000748 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
749 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
750 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000751 data_actlen = 0;
752 /* no data, go immediately to the STATUS phase */
753 if (srb->datalen == 0)
754 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530755 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000756 if (dir_in)
757 pipe = pipein;
758 else
759 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300760
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100761 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
762 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000763 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100764 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530765 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000766 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100767 result = usb_stor_BBB_clear_endpt_stall(us,
768 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000769 if (result >= 0)
770 /* continue on to STATUS phase */
771 goto st;
772 }
773 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530774 debug("usb_bulk_msg error status %ld\n",
775 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000776 usb_stor_BBB_reset(us);
777 return USB_STOR_TRANSPORT_FAILED;
778 }
779#ifdef BBB_XPORT_TRACE
780 for (index = 0; index < data_actlen; index++)
781 printf("pdata[%d] %#x ", index, srb->pdata[index]);
782 printf("\n");
783#endif
784 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100785st:
wdenk149dded2003-09-10 18:20:28 +0000786 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100787again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530788 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530789 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200790 &actlen, USB_CNTL_TIMEOUT*5);
791
wdenk149dded2003-09-10 18:20:28 +0000792 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100793 if ((result < 0) && (retry < 1) &&
794 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530795 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000796 /* clear the STALL on the endpoint */
797 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
798 if (result >= 0 && (retry++ < 1))
799 /* do a retry */
800 goto again;
801 }
802 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530803 debug("usb_bulk_msg error status %ld\n",
804 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000805 usb_stor_BBB_reset(us);
806 return USB_STOR_TRANSPORT_FAILED;
807 }
808#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530809 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000810 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
811 printf("ptr[%d] %#x ", index, ptr[index]);
812 printf("\n");
813#endif
814 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530815 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000816 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
817 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530818 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530819 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000820 usb_stor_BBB_reset(us);
821 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530822 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530823 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000824 usb_stor_BBB_reset(us);
825 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530826 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530827 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000828 usb_stor_BBB_reset(us);
829 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530830 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530831 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000832 usb_stor_BBB_reset(us);
833 return USB_STOR_TRANSPORT_FAILED;
834 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530835 debug("transferred %dB instead of %ldB\n",
836 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000837 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530838 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530839 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000840 return USB_STOR_TRANSPORT_FAILED;
841 }
842
843 return result;
844}
845
Kim Phillips199adb62012-10-29 13:34:32 +0000846static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000847{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000849 ccb *psrb;
850 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100851 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000852
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200853 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100854 status = USB_STOR_TRANSPORT_GOOD;
855 retry = 0;
856 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000857 /* issue the command */
858do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100859 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530860 debug("command / Data returned %d, status %lX\n",
861 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000862 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100863 if (us->protocol == US_PR_CBI) {
864 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000865 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530867 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000868 return status;
869 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
871 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
872 if (!us->ip_data) {
873 /* if the status is good, report it */
874 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530875 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000876 return status;
877 }
878 }
879 }
880 /* do we have to issue an auto request? */
881 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100882 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530883 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000884 us->transport_reset(us);
885 return USB_STOR_TRANSPORT_ERROR;
886 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100887 if ((us->protocol == US_PR_CBI) &&
888 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
889 (srb->cmd[0] == SCSI_INQUIRY))) {
890 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530891 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000892 return USB_STOR_TRANSPORT_GOOD;
893 }
894 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100895 memset(&psrb->cmd[0], 0, 12);
896 psrb->cmd[0] = SCSI_REQ_SENSE;
897 psrb->cmd[1] = srb->lun << 5;
898 psrb->cmd[4] = 18;
899 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200900 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100901 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000902 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100903 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530904 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000905 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906 if (us->protocol == US_PR_CBI)
907 status = usb_stor_CBI_get_status(psrb, us);
908
909 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530910 debug(" AUTO REQUEST ERROR %ld\n",
911 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000912 return USB_STOR_TRANSPORT_ERROR;
913 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530914 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
915 srb->sense_buf[0], srb->sense_buf[2],
916 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000917 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100918 if ((srb->sense_buf[2] == 0) &&
919 (srb->sense_buf[12] == 0) &&
920 (srb->sense_buf[13] == 0)) {
921 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000922 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923 }
924
wdenkaffae2b2002-08-17 09:36:01 +0000925 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100926 switch (srb->sense_buf[2]) {
927 case 0x01:
928 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000929 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000930 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100931 case 0x02:
932 /* Not Ready */
933 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
934 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
935 " 0x%02X (NOT READY)\n", srb->cmd[0],
936 srb->sense_buf[0], srb->sense_buf[2],
937 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000938 return USB_STOR_TRANSPORT_FAILED;
939 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000940 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000941 goto do_retry;
942 }
943 break;
944 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100945 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
946 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
947 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
948 srb->sense_buf[2], srb->sense_buf[12],
949 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000950 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100951 } else
wdenk149dded2003-09-10 18:20:28 +0000952 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000953 break;
wdenkaffae2b2002-08-17 09:36:01 +0000954 }
955 return USB_STOR_TRANSPORT_FAILED;
956}
957
958
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100959static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000960{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100961 int retry, i;
962 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000963 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100964 memset(&srb->cmd[0], 0, 12);
965 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200966 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967 srb->cmd[4] = 36;
968 srb->datalen = 36;
969 srb->cmdlen = 12;
970 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530971 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100972 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000973 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200974 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000975
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000977 printf("error in inquiry\n");
978 return -1;
979 }
980 return 0;
981}
982
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100983static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000984{
985 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000986
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 ptr = (char *)srb->pdata;
988 memset(&srb->cmd[0], 0, 12);
989 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200990 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100991 srb->cmd[4] = 18;
992 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200993 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100994 srb->cmdlen = 12;
995 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530996 debug("Request Sense returned %02X %02X %02X\n",
997 srb->sense_buf[2], srb->sense_buf[12],
998 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100999 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001000 return 0;
1001}
1002
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001003static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001004{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001005 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001006
wdenkaffae2b2002-08-17 09:36:01 +00001007 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001008 memset(&srb->cmd[0], 0, 12);
1009 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001010 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001011 srb->datalen = 0;
1012 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001013 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1014 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001015 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001016 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001017 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -08001018 /*
1019 * Check the Key Code Qualifier, if it matches
1020 * "Not Ready - medium not present"
1021 * (the sense Key equals 0x2 and the ASC is 0x3a)
1022 * return immediately as the medium being absent won't change
1023 * unless there is a user action.
1024 */
1025 if ((srb->sense_buf[2] == 0x02) &&
1026 (srb->sense_buf[12] == 0x3a))
1027 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +00001028 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001029 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001030
wdenkaffae2b2002-08-17 09:36:01 +00001031 return -1;
1032}
1033
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001034static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001035{
1036 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001037 /* XXX retries */
1038 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001039 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001040 memset(&srb->cmd[0], 0, 12);
1041 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001042 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001043 srb->datalen = 8;
1044 srb->cmdlen = 12;
1045 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001046 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001047 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001048
wdenkaffae2b2002-08-17 09:36:01 +00001049 return -1;
1050}
1051
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001052static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
1053 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001054{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 memset(&srb->cmd[0], 0, 12);
1056 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001057 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001058 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1059 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1060 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1061 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1062 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1063 srb->cmd[8] = (unsigned char) blocks & 0xff;
1064 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301065 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001066 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001067}
1068
Mahavir Jain127e1082009-11-03 12:22:10 +05301069static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1070 unsigned short blocks)
1071{
1072 memset(&srb->cmd[0], 0, 12);
1073 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001074 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301075 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1076 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1077 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1078 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1079 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1080 srb->cmd[8] = (unsigned char) blocks & 0xff;
1081 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301082 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301083 return ss->transport(srb, ss);
1084}
1085
wdenkaffae2b2002-08-17 09:36:01 +00001086
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001087#ifdef CONFIG_USB_BIN_FIXUP
1088/*
1089 * Some USB storage devices queried for SCSI identification data respond with
1090 * binary strings, which if output to the console freeze the terminal. The
1091 * workaround is to modify the vendor and product strings read from such
1092 * device with proper values (as reported by 'usb info').
1093 *
1094 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001095 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001096 */
1097static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1098 unsigned char vendor[],
1099 unsigned char product[]) {
1100 const unsigned char max_vendor_len = 40;
1101 const unsigned char max_product_len = 20;
1102 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001103 strncpy((char *)vendor, "SMSC", max_vendor_len);
1104 strncpy((char *)product, "Flash Media Cntrller",
1105 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001106 }
1107}
1108#endif /* CONFIG_USB_BIN_FIXUP */
1109
Simon Glass07b2b782016-02-29 15:25:58 -07001110#ifdef CONFIG_BLK
1111static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1112 lbaint_t blkcnt, void *buffer)
1113#else
Simon Glass4101f682016-02-29 15:25:34 -07001114static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001115 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001116#endif
wdenkaffae2b2002-08-17 09:36:01 +00001117{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001118 lbaint_t start, blks;
1119 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001120 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001121 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001122 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001123 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001124 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001125#ifdef CONFIG_BLK
1126 struct blk_desc *block_dev;
1127#endif
wdenkf8d813e2004-03-02 14:05:39 +00001128
1129 if (blkcnt == 0)
1130 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001131 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001132#ifdef CONFIG_BLK
1133 block_dev = dev_get_uclass_platdata(dev);
1134 udev = dev_get_parent_priv(dev_get_parent(dev));
1135 debug("\nusb_read: udev %d\n", block_dev->devnum);
1136#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001137 debug("\nusb_read: udev %d\n", block_dev->devnum);
1138 udev = usb_dev_desc[block_dev->devnum].priv;
1139 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001140 debug("%s: No device\n", __func__);
1141 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001142 }
Simon Glass07b2b782016-02-29 15:25:58 -07001143#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001144 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001145
1146 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass9807c3b2016-02-29 15:25:54 -07001147 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001148 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001149 start = blknr;
1150 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001151
Simon Glass9807c3b2016-02-29 15:25:54 -07001152 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1153 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001154
wdenkaffae2b2002-08-17 09:36:01 +00001155 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001156 /* XXX need some comment here */
1157 retry = 2;
1158 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001159 if (blks > USB_MAX_XFER_BLK)
1160 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001161 else
1162 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001163retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001164 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001165 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001166 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001167 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001168 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301169 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001170 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001171 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001172 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001173 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001174 break;
1175 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001176 start += smallblks;
1177 blks -= smallblks;
1178 buf_addr += srb->datalen;
1179 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001180 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001181
Vivek Gautamceb49722013-04-12 16:34:33 +05301182 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001183 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301184 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001185
wdenkaffae2b2002-08-17 09:36:01 +00001186 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001187 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001188 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001189 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001190}
1191
Simon Glass07b2b782016-02-29 15:25:58 -07001192#ifdef CONFIG_BLK
1193static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1194 lbaint_t blkcnt, const void *buffer)
1195#else
Simon Glass4101f682016-02-29 15:25:34 -07001196static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001197 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001198#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301199{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001200 lbaint_t start, blks;
1201 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301202 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001203 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001204 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001205 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301206 ccb *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001207#ifdef CONFIG_BLK
1208 struct blk_desc *block_dev;
1209#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301210
1211 if (blkcnt == 0)
1212 return 0;
1213
Mahavir Jain127e1082009-11-03 12:22:10 +05301214 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001215#ifdef CONFIG_BLK
1216 block_dev = dev_get_uclass_platdata(dev);
1217 udev = dev_get_parent_priv(dev_get_parent(dev));
1218 debug("\nusb_read: udev %d\n", block_dev->devnum);
1219#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001220 debug("\nusb_read: udev %d\n", block_dev->devnum);
1221 udev = usb_dev_desc[block_dev->devnum].priv;
1222 if (!udev) {
1223 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001224 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001225 }
Simon Glass07b2b782016-02-29 15:25:58 -07001226#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001227 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301228
1229 usb_disable_asynch(1); /* asynch transfer not allowed */
1230
Simon Glass9807c3b2016-02-29 15:25:54 -07001231 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001232 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301233 start = blknr;
1234 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301235
Simon Glass9807c3b2016-02-29 15:25:54 -07001236 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1237 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301238
1239 do {
1240 /* If write fails retry for max retry count else
1241 * return with number of blocks written successfully.
1242 */
1243 retry = 2;
1244 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001245 if (blks > USB_MAX_XFER_BLK)
1246 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301247 else
1248 smallblks = (unsigned short) blks;
1249retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001250 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301251 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001252 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301253 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001254 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301255 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001256 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301257 if (retry--)
1258 goto retry_it;
1259 blkcnt -= blks;
1260 break;
1261 }
1262 start += smallblks;
1263 blks -= smallblks;
1264 buf_addr += srb->datalen;
1265 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001266 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301267
Simon Glass4fd074d2014-10-15 04:38:38 -06001268 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1269 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301270
1271 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001272 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001273 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301274 return blkcnt;
1275
1276}
wdenkaffae2b2002-08-17 09:36:01 +00001277
1278/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001279int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1280 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001281{
Tom Rix8f8bd562009-10-31 12:37:38 -05001282 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001283 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301284 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001285 unsigned int flags = 0;
1286
wdenkaffae2b2002-08-17 09:36:01 +00001287 /* let's examine the device now */
1288 iface = &dev->config.if_desc[ifnum];
1289
wdenkaffae2b2002-08-17 09:36:01 +00001290 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001291 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1292 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1293 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001294 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001295 /* if it's not a mass storage, we go no further */
1296 return 0;
1297 }
1298
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001299 memset(ss, 0, sizeof(struct us_data));
1300
wdenkaffae2b2002-08-17 09:36:01 +00001301 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301302 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001303
1304 /* Initialize the us_data structure with some useful info */
1305 ss->flags = flags;
1306 ss->ifnum = ifnum;
1307 ss->pusb_dev = dev;
1308 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001309 ss->subclass = iface->desc.bInterfaceSubClass;
1310 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001311
1312 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301313 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001314 switch (ss->protocol) {
1315 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301316 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001317 ss->transport = usb_stor_CB_transport;
1318 ss->transport_reset = usb_stor_CB_reset;
1319 break;
1320
1321 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301322 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001323 ss->transport = usb_stor_CB_transport;
1324 ss->transport_reset = usb_stor_CB_reset;
1325 break;
wdenk149dded2003-09-10 18:20:28 +00001326 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301327 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001328 ss->transport = usb_stor_BBB_transport;
1329 ss->transport_reset = usb_stor_BBB_reset;
1330 break;
wdenkaffae2b2002-08-17 09:36:01 +00001331 default:
wdenk80885a92004-02-26 23:46:20 +00001332 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001333 return 0;
1334 break;
1335 }
1336
1337 /*
1338 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1339 * An optional interrupt is OK (necessary for CBI protocol).
1340 * We will ignore any others.
1341 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001342 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301343 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001344 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301345 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001346 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301347 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1348 ss->ep_in = ep_desc->bEndpointAddress &
1349 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001350 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001351 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301352 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001353 USB_ENDPOINT_NUMBER_MASK;
1354 }
1355
1356 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301357 if ((ep_desc->bmAttributes &
1358 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1359 ss->ep_int = ep_desc->bEndpointAddress &
1360 USB_ENDPOINT_NUMBER_MASK;
1361 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001362 }
1363 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301364 debug("Endpoints In %d Out %d Int %d\n",
1365 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001366
1367 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001368 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001369 !ss->ep_in || !ss->ep_out ||
1370 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301371 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001372 return 0;
1373 }
1374 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001375 /* We only handle certain protocols. Currently, these are
1376 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001377 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001378 */
wdenk80885a92004-02-26 23:46:20 +00001379 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1380 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001381 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001382 return 0;
1383 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001384 if (ss->ep_int) {
1385 /* we had found an interrupt endpoint, prepare irq pipe
1386 * set up the IRQ pipe and handler
1387 */
wdenkaffae2b2002-08-17 09:36:01 +00001388 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1389 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1390 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001391 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001392 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001393 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001394 return 1;
1395}
1396
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001397int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001398 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001399{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001400 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001401 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1402 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1403 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001404 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001405
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001406 pccb->pdata = usb_stor_buf;
1407
1408 dev_desc->target = dev->devnum;
1409 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301410 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001411
Simon Glass1d5827a2015-03-25 12:22:12 -06001412 if (usb_inquiry(pccb, ss)) {
1413 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001414 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001415 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001416
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001417 perq = usb_stor_buf[0];
1418 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001419
Soeren Moch6a559bb2014-11-08 07:02:14 +01001420 /*
1421 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1422 * they would not respond to test_unit_ready .
1423 */
1424 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001425 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001426 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001427 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001428 if ((modi&0x80) == 0x80) {
1429 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001430 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001431 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001432 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1433 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1434 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001435 dev_desc->vendor[8] = 0;
1436 dev_desc->product[16] = 0;
1437 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001438#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001439 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1440 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001441#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301442 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1443 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001444 if (usb_test_unit_ready(pccb, ss)) {
1445 printf("Device NOT ready\n"
1446 " Request Sense returned %02X %02X %02X\n",
1447 pccb->sense_buf[2], pccb->sense_buf[12],
1448 pccb->sense_buf[13]);
1449 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001450 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001451 return 1;
1452 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001453 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001454 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001455 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001456 memset(pccb->pdata, 0, 8);
1457 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001458 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001459 cap[0] = 2880;
1460 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001461 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001462 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001463 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001464#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001465 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1466 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001467
Christian Eggersc9182612008-05-21 22:12:00 +02001468 cap[0] = cpu_to_be32(cap[0]);
1469 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001470#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001471
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001472 capacity = be32_to_cpu(cap[0]) + 1;
1473 blksz = be32_to_cpu(cap[1]);
1474
1475 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1476 dev_desc->lba = capacity;
1477 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001478 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001479 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301480 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001481
wdenkaffae2b2002-08-17 09:36:01 +00001482 return 1;
1483}
Simon Glassacf277a2015-03-25 12:22:16 -06001484
1485#ifdef CONFIG_DM_USB
1486
1487static int usb_mass_storage_probe(struct udevice *dev)
1488{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001489 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001490 int ret;
1491
1492 usb_disable_asynch(1); /* asynch transfer not allowed */
1493 ret = usb_stor_probe_device(udev);
1494 usb_disable_asynch(0); /* asynch transfer allowed */
1495
1496 return ret;
1497}
1498
1499static const struct udevice_id usb_mass_storage_ids[] = {
1500 { .compatible = "usb-mass-storage" },
1501 { }
1502};
1503
1504U_BOOT_DRIVER(usb_mass_storage) = {
1505 .name = "usb_mass_storage",
1506 .id = UCLASS_MASS_STORAGE,
1507 .of_match = usb_mass_storage_ids,
1508 .probe = usb_mass_storage_probe,
Simon Glass07b2b782016-02-29 15:25:58 -07001509#ifdef CONFIG_BLK
1510 .platdata_auto_alloc_size = sizeof(struct us_data),
1511#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001512};
1513
1514UCLASS_DRIVER(usb_mass_storage) = {
1515 .id = UCLASS_MASS_STORAGE,
1516 .name = "usb_mass_storage",
1517};
1518
1519static const struct usb_device_id mass_storage_id_table[] = {
1520 {
1521 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1522 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1523 },
1524 { } /* Terminating entry */
1525};
1526
Simon Glassabb59cf2015-07-06 16:47:51 -06001527U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001528#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001529
Simon Glass07b2b782016-02-29 15:25:58 -07001530#ifdef CONFIG_BLK
1531static const struct blk_ops usb_storage_ops = {
1532 .read = usb_stor_read,
1533 .write = usb_stor_write,
1534};
1535
1536U_BOOT_DRIVER(usb_storage_blk) = {
1537 .name = "usb_storage_blk",
1538 .id = UCLASS_BLK,
1539 .ops = &usb_storage_ops,
1540};
Simon Glassc0543bf2016-05-01 11:36:06 -06001541#else
1542U_BOOT_LEGACY_BLK(usb) = {
1543 .if_typename = "usb",
1544 .if_type = IF_TYPE_USB,
1545 .max_devs = USB_MAX_STOR_DEV,
1546 .desc = usb_dev_desc,
1547};
Simon Glassacf277a2015-03-25 12:22:16 -06001548#endif