blob: 291728f37e0adc44d8fef204e841a3c2e66a3f43 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00002/*
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +02003 * Most of this source has been derived from the Linux USB
4 * project:
5 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
6 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
7 * (c) 1999 Michael Gee (michael@linuxspecific.com)
8 * (c) 2000 Yggdrasil Computing, Inc.
9 *
10 *
11 * Adapted for U-Boot:
12 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
Simon Glassac9774e2015-03-25 12:22:16 -060013 * Driver model conversion:
14 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000015 *
wdenkde887eb2003-09-10 18:20:28 +000016 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020017 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000018 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020019 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000020 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000021 */
22
23/* Note:
24 * Currently only the CBI transport protocoll has been implemented, and it
25 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
26 * transport protocoll may work as well.
27 */
wdenkde887eb2003-09-10 18:20:28 +000028/*
29 * New Note:
30 * Support for USB Mass Storage Devices (BBB) has been added. It has
31 * only been tested with USB memory sticks.
wdenkde887eb2003-09-10 18:20:28 +000032 */
wdenkaffae2b2002-08-17 09:36:01 +000033
34
wdenkaffae2b2002-08-17 09:36:01 +000035#include <common.h>
Simon Glass655306c2020-05-10 11:39:58 -060036#include <blk.h>
wdenkaffae2b2002-08-17 09:36:01 +000037#include <command.h>
Simon Glassac9774e2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060040#include <log.h>
Simon Glass332a9b62015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020043#include <asm/byteorder.h>
Simon Glass274e0b02020-05-10 11:39:56 -060044#include <asm/cache.h>
wdenkaffae2b2002-08-17 09:36:01 +000045#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060046#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070047#include <dm/lists.h>
Simon Glassdbd79542020-05-10 11:40:11 -060048#include <linux/delay.h>
wdenkaffae2b2002-08-17 09:36:01 +000049
Grant Likelyffc2dd72007-02-20 09:04:34 +010050#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000051#include <usb.h>
52
wdenk5f495752004-02-26 23:46:20 +000053#undef BBB_COMDAT_TRACE
54#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000055
wdenkaffae2b2002-08-17 09:36:01 +000056#include <scsi.h>
57/* direction table -- this indicates the direction of the data
58 * transfer for each command code -- a 1 indicates input
59 */
Mike Frysinger165522b2010-10-20 07:16:04 -040060static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000061 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
62 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
65};
66#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
67
Simon Glass5fb559d2017-06-14 21:28:30 -060068static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010069static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000070
Michael Trimarchi956a4352008-12-10 15:52:06 +010071static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000072
Sven Schwermerc58ff202018-11-21 08:43:57 +010073#if !CONFIG_IS_ENABLED(BLK)
Simon Glasse3394752016-02-29 15:25:34 -070074static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070075#endif
wdenkaffae2b2002-08-17 09:36:01 +000076
77struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060078typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010079typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000080
81struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010082 struct usb_device *pusb_dev; /* this usb_device */
83
84 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020085# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010086 unsigned char ifnum; /* interface number */
87 unsigned char ep_in; /* in endpoint */
88 unsigned char ep_out; /* out ....... */
89 unsigned char ep_int; /* interrupt . */
90 unsigned char subclass; /* as in overview */
91 unsigned char protocol; /* .............. */
92 unsigned char attention_done; /* force attn on first cmd */
93 unsigned short ip_data; /* interrupt data */
94 int action; /* what to do */
95 int ip_wanted; /* needed */
96 int *irq_handle; /* for USB int requests */
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020097 unsigned int irqpipe; /* pipe for release_irq */
Michael Trimarchi956a4352008-12-10 15:52:06 +010098 unsigned char irqmaxp; /* max packed for irq Pipe */
99 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -0600100 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100101 trans_reset transport_reset; /* reset routine */
102 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -0700103 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000104};
105
Sven Schwermerc58ff202018-11-21 08:43:57 +0100106#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000107static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700108#endif
wdenkaffae2b2002-08-17 09:36:01 +0000109
wdenk5f495752004-02-26 23:46:20 +0000110#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000111#define USB_STOR_TRANSPORT_FAILED -1
112#define USB_STOR_TRANSPORT_ERROR -2
113
Michael Trimarchi956a4352008-12-10 15:52:06 +0100114int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700115 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100116int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
117 struct us_data *ss);
Sven Schwermerc58ff202018-11-21 08:43:57 +0100118#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700119static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
120 lbaint_t blkcnt, void *buffer);
121static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
122 lbaint_t blkcnt, const void *buffer);
123#else
Simon Glasse3394752016-02-29 15:25:34 -0700124static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700125 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700126static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700127 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700128#endif
wdenkaffae2b2002-08-17 09:36:01 +0000129void uhci_show_temp_int_td(void);
130
Kim Phillipsb052b602012-10-29 13:34:32 +0000131static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000132{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200133 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000134}
135
Michael Trimarchi956a4352008-12-10 15:52:06 +0100136/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200137 * show info on storage devices; 'usb start/init' must be invoked earlier
138 * as we only retrieve structures populated during devices initialization
139 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100140int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200141{
Simon Glass99e598e2016-02-29 15:25:54 -0700142 int count = 0;
Sven Schwermerc58ff202018-11-21 08:43:57 +0100143#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700144 struct udevice *dev;
145
146 for (blk_first_device(IF_TYPE_USB, &dev);
147 dev;
148 blk_next_device(&dev)) {
Simon Glass71fa5b42020-12-03 16:55:18 -0700149 struct blk_desc *desc = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700150
151 printf(" Device %d: ", desc->devnum);
152 dev_print(desc);
153 count++;
154 }
155#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200156 int i;
157
Aras Vaichas7ede1862008-03-25 12:09:07 +1100158 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200159 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100160 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200161 dev_print(&usb_dev_desc[i]);
162 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100163 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100164 }
Simon Glass01f5be92016-02-29 15:25:58 -0700165#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700166 if (!count) {
167 printf("No storage devices, perhaps not 'usb start'ed..?\n");
168 return 1;
169 }
170
Simon Glass8c6c0742016-03-16 07:45:44 -0600171 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200172}
173
Ludovic Courtès134396c2010-10-05 22:04:26 +0200174static unsigned int usb_get_max_lun(struct us_data *us)
175{
176 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530177 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200178 len = usb_control_msg(us->pusb_dev,
179 usb_rcvctrlpipe(us->pusb_dev, 0),
180 US_BBB_GET_MAX_LUN,
181 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
182 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530183 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200184 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530185 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530186 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200187}
188
Simon Glass99e598e2016-02-29 15:25:54 -0700189static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600190{
Simon Glass99e598e2016-02-29 15:25:54 -0700191 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700192
Sven Schwermerc58ff202018-11-21 08:43:57 +0100193#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700194 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700195 int ret;
196#else
Simon Glass99e598e2016-02-29 15:25:54 -0700197 int start;
198
199 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600200 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700201#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600202
Simon Glass01f5be92016-02-29 15:25:58 -0700203 debug("\n\nProbing for storage\n");
Sven Schwermerc58ff202018-11-21 08:43:57 +0100204#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700205 /*
Simon Glass71fa5b42020-12-03 16:55:18 -0700206 * We store the us_data in the mass storage device's plat. It
Simon Glass01f5be92016-02-29 15:25:58 -0700207 * is shared by all LUNs (block devices) attached to this mass storage
208 * device.
209 */
Simon Glassfa20e932020-12-03 16:55:20 -0700210 data = dev_get_plat(udev->dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700211 if (!usb_storage_probe(udev, 0, data))
212 return 0;
213 max_lun = usb_get_max_lun(data);
214 for (lun = 0; lun <= max_lun; lun++) {
215 struct blk_desc *blkdev;
216 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600217 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700218
Simon Glass966b6952016-05-01 11:36:29 -0600219 snprintf(str, sizeof(str), "lun%d", lun);
220 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
221 IF_TYPE_USB, usb_max_devs, 512, 0,
222 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700223 if (ret) {
224 debug("Cannot bind driver\n");
225 return ret;
226 }
227
Simon Glass71fa5b42020-12-03 16:55:18 -0700228 blkdev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700229 blkdev->target = 0xff;
230 blkdev->lun = lun;
231
232 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengcbc3da82018-10-15 02:21:07 -0700233 if (ret == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700234 usb_max_devs++;
235 debug("%s: Found device %p\n", __func__, udev);
236 } else {
237 debug("usb_stor_get_info: Invalid device\n");
238 ret = device_unbind(dev);
239 if (ret)
240 return ret;
241 }
AKASHI Takahirof9c3cc82022-03-08 20:36:40 +0900242
243 ret = blk_probe_or_unbind(dev);
244 if (ret)
245 return ret;
Simon Glass01f5be92016-02-29 15:25:58 -0700246 }
247#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700248 /* We don't have space to even probe if we hit the maximum */
249 if (usb_max_devs == USB_MAX_STOR_DEV) {
250 printf("max USB Storage Device reached: %d stopping\n",
251 usb_max_devs);
252 return -ENOSPC;
253 }
254
Simon Glass99e598e2016-02-29 15:25:54 -0700255 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
256 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600257
Simon Glass99e598e2016-02-29 15:25:54 -0700258 /*
259 * OK, it's a storage device. Iterate over its LUNs and populate
260 * usb_dev_desc'
261 */
262 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600263
Simon Glass99e598e2016-02-29 15:25:54 -0700264 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
265 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
266 lun++) {
267 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600268
Simon Glass99e598e2016-02-29 15:25:54 -0700269 blkdev = &usb_dev_desc[usb_max_devs];
270 memset(blkdev, '\0', sizeof(struct blk_desc));
271 blkdev->if_type = IF_TYPE_USB;
272 blkdev->devnum = usb_max_devs;
273 blkdev->part_type = PART_TYPE_UNKNOWN;
274 blkdev->target = 0xff;
275 blkdev->type = DEV_TYPE_UNKNOWN;
276 blkdev->block_read = usb_stor_read;
277 blkdev->block_write = usb_stor_write;
278 blkdev->lun = lun;
279 blkdev->priv = udev;
280
281 if (usb_stor_get_info(udev, &usb_stor[start],
282 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700283 debug("partype: %d\n", blkdev->part_type);
284 part_init(blkdev);
285 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700286 usb_max_devs++;
287 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600288 }
289 }
Simon Glass01f5be92016-02-29 15:25:58 -0700290#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600291
Simon Glassdf7d34f2015-03-25 12:22:15 -0600292 return 0;
293}
294
295void usb_stor_reset(void)
296{
297 usb_max_devs = 0;
298}
299
Michael Trimarchi956a4352008-12-10 15:52:06 +0100300/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200301 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000302 * to the user if mode = 1
303 * returns current device or -1 if no
304 */
305int usb_stor_scan(int mode)
306{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100307 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200308 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100309
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100310#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100311 unsigned char i;
312
wdenkaffae2b2002-08-17 09:36:01 +0000313 usb_disable_asynch(1); /* asynch transfer not allowed */
314
Simon Glassdf7d34f2015-03-25 12:22:15 -0600315 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100316 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600317 struct usb_device *dev;
318
Michael Trimarchi956a4352008-12-10 15:52:06 +0100319 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530320 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600321 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000322 break;
wdenkaffae2b2002-08-17 09:36:01 +0000323 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200324
wdenkaffae2b2002-08-17 09:36:01 +0000325 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100326#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200327 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100328 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000329 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100330 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000331}
332
333static int usb_stor_irq(struct usb_device *dev)
334{
335 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100336 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000337
Michael Trimarchi956a4352008-12-10 15:52:06 +0100338 if (us->ip_wanted)
339 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000340 return 0;
341}
342
343
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530344#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000345
Simon Glass5fb559d2017-06-14 21:28:30 -0600346static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000347{
348 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100349 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
350 for (i = 0; i < 12; i++)
351 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000352 printf("\n");
353}
354
355static void display_int_status(unsigned long tmp)
356{
357 printf("Status: %s %s %s %s %s %s %s\n",
358 (tmp & USB_ST_ACTIVE) ? "Active" : "",
359 (tmp & USB_ST_STALLED) ? "Stalled" : "",
360 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
361 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
362 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
363 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
364 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
365}
366#endif
367/***********************************************************************
368 * Data transfer routines
369 ***********************************************************************/
370
371static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
372{
373 int max_size;
374 int this_xfer;
375 int result;
376 int partial;
377 int maxtry;
378 int stat;
379
380 /* determine the maximum packet size for these transfers */
381 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
382
383 /* while we have data left to transfer */
384 while (length) {
385
386 /* calculate how long this will be -- maximum or a remainder */
387 this_xfer = length > max_size ? max_size : length;
388 length -= this_xfer;
389
390 /* setup the retry counter */
391 maxtry = 10;
392
393 /* set up the transfer loop */
394 do {
395 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600396 debug("Bulk xfer 0x%lx(%d) try #%d\n",
397 (ulong)map_to_sysmem(buf), this_xfer,
398 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000399 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100400 this_xfer, &partial,
401 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530402 debug("bulk_msg returned %d xferred %d/%d\n",
403 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100404 if (us->pusb_dev->status != 0) {
405 /* if we stall, we need to clear it before
406 * we go on
407 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530408#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000409 display_int_status(us->pusb_dev->status);
410#endif
411 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530412 debug("stalled ->clearing endpoint" \
413 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000414 stat = us->pusb_dev->status;
415 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100416 us->pusb_dev->status = stat;
417 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530418 debug("bulk transferred" \
419 "with error %lX," \
420 " but data ok\n",
421 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000422 return 0;
423 }
424 else
425 return result;
426 }
427 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530428 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000429 return result;
430 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530431 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100432 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530433 debug(" %ld, but data ok\n",
434 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000435 return 0;
436 }
437 /* if our try counter reaches 0, bail out */
Michal Simekcfd8a6e2020-12-01 14:02:58 +0100438 debug(" %ld, data %d\n",
439 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000440 if (!maxtry--)
441 return result;
442 }
443 /* update to show what data was transferred */
444 this_xfer -= partial;
445 buf += partial;
446 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100447 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000448 }
449
450 /* if we get here, we're done and successful */
451 return 0;
452}
453
wdenkde887eb2003-09-10 18:20:28 +0000454static int usb_stor_BBB_reset(struct us_data *us)
455{
456 int result;
457 unsigned int pipe;
458
459 /*
460 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
461 *
462 * For Reset Recovery the host shall issue in the following order:
463 * a) a Bulk-Only Mass Storage Reset
464 * b) a Clear Feature HALT to the Bulk-In endpoint
465 * c) a Clear Feature HALT to the Bulk-Out endpoint
466 *
467 * This is done in 3 steps.
468 *
469 * If the reset doesn't succeed, the device should be port reset.
470 *
471 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
472 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530473 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100474 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
475 US_BBB_RESET,
476 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000477 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200478
Michael Trimarchi956a4352008-12-10 15:52:06 +0100479 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530480 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000481 return -1;
482 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200483
wdenkde887eb2003-09-10 18:20:28 +0000484 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000485 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530486 debug("BBB_reset result %d: status %lX reset\n",
487 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000488 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
489 result = usb_clear_halt(us->pusb_dev, pipe);
490 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
493 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000494 /* long wait for reset */
495 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
496 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000497 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530498 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
499 result, us->pusb_dev->status);
500 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000501 return 0;
502}
503
wdenkaffae2b2002-08-17 09:36:01 +0000504/* FIXME: this reset function doesn't really reset the port, and it
505 * should. Actually it should probably do what it's doing here, and
506 * reset the port physically
507 */
508static int usb_stor_CB_reset(struct us_data *us)
509{
510 unsigned char cmd[12];
511 int result;
512
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530513 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100514 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000515 cmd[0] = SCSI_SEND_DIAG;
516 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100517 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
518 US_CBI_ADSC,
519 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
520 0, us->ifnum, cmd, sizeof(cmd),
521 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000522
523 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000524 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530525 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
526 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000527 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
528 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
529
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530530 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000531 return 0;
532}
533
wdenkde887eb2003-09-10 18:20:28 +0000534/*
535 * Set up the command for a BBB device. Note that the actual SCSI
536 * command is copied into cbw.CBWCDB.
537 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600538static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000539{
540 int result;
541 int actlen;
542 int dir_in;
543 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600544 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000545
546 dir_in = US_DIRECTION(srb->cmd[0]);
547
548#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530549 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100550 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
551 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000552 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100553 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000554 printf("cmd[%d] %#x ", result, srb->cmd[result]);
555 printf("\n");
556 }
557#endif
558 /* sanity checks */
559 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530560 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000561 return -1;
562 }
563
564 /* always OUT to the ep */
565 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
566
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530567 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
568 cbw->dCBWTag = cpu_to_le32(CBWTag++);
569 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
570 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
571 cbw->bCBWLUN = srb->lun;
572 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000573 /* copy the command data into the CBW command data buffer */
574 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300575
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530576 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
577 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100578 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000579 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530580 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000581 return result;
582}
583
wdenkaffae2b2002-08-17 09:36:01 +0000584/* FIXME: we also need a CBI_command which sets up the completion
585 * interrupt, and waits for it
586 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600587static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000588{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200589 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000591 unsigned int pipe;
592 unsigned long status;
593
Michael Trimarchi956a4352008-12-10 15:52:06 +0100594 retry = 5;
595 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000596
Michael Trimarchi956a4352008-12-10 15:52:06 +0100597 if (dir_in)
598 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
599 else
600 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
601
602 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530603 debug("CBI gets a command: Try %d\n", 5 - retry);
604#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000605 usb_show_srb(srb);
606#endif
607 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100608 result = usb_control_msg(us->pusb_dev,
609 usb_sndctrlpipe(us->pusb_dev , 0),
610 US_CBI_ADSC,
611 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000612 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100613 srb->cmd, srb->cmdlen,
614 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530615 debug("CB_transport: control msg returned %d, status %lX\n",
616 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000617 /* check the return code for the command */
618 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100619 if (us->pusb_dev->status & USB_ST_STALLED) {
620 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530621 debug(" stall during command found," \
622 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100623 usb_clear_halt(us->pusb_dev,
624 usb_sndctrlpipe(us->pusb_dev, 0));
625 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000626 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530627 debug(" error during command %02X" \
628 " Stat = %lX\n", srb->cmd[0],
629 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000630 return result;
631 }
632 /* transfer the data payload for this command, if one exists*/
633
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530634 debug("CB_transport: control msg returned %d," \
635 " direction is %s to go 0x%lx\n", result,
636 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000637 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100638 result = us_one_transfer(us, pipe, (char *)srb->pdata,
639 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530640 debug("CBI attempted to transfer data," \
641 " result is %d status %lX, len %d\n",
642 result, us->pusb_dev->status,
643 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100644 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000645 break;
646 } /* if (srb->datalen) */
647 else
648 break;
649 }
650 /* return result */
651
652 return result;
653}
654
655
Simon Glass5fb559d2017-06-14 21:28:30 -0600656static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000657{
658 int timeout;
659
wdenk5f495752004-02-26 23:46:20 +0000660 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200661 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200662 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000663 timeout = 1000;
664 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300665 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000666 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000667 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000668 }
669 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100670 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000671 us->ip_wanted = 0;
672 return USB_STOR_TRANSPORT_ERROR;
673 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700674 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530675 us->ip_data, us->pusb_dev->irq_act_len,
676 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000677 /* UFI gives us ASC and ASCQ, like a request sense */
678 if (us->subclass == US_SC_UFI) {
679 if (srb->cmd[0] == SCSI_REQ_SENSE ||
680 srb->cmd[0] == SCSI_INQUIRY)
681 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000682 else if (us->ip_data)
683 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000684 else
wdenk5f495752004-02-26 23:46:20 +0000685 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000686 }
687 /* otherwise, we interpret the data normally */
688 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000689 case 0x0001:
690 return USB_STOR_TRANSPORT_GOOD;
691 case 0x0002:
692 return USB_STOR_TRANSPORT_FAILED;
693 default:
694 return USB_STOR_TRANSPORT_ERROR;
695 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000696 return USB_STOR_TRANSPORT_ERROR;
697}
698
699#define USB_TRANSPORT_UNKNOWN_RETRY 5
700#define USB_TRANSPORT_NOT_READY_RETRY 10
701
wdenkde887eb2003-09-10 18:20:28 +0000702/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000703static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000704{
wdenkde887eb2003-09-10 18:20:28 +0000705 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900706 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
707 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
708 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000709}
710
Simon Glass5fb559d2017-06-14 21:28:30 -0600711static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000712{
713 int result, retry;
714 int dir_in;
715 int actlen, data_actlen;
716 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600717 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000718#ifdef BBB_XPORT_TRACE
719 unsigned char *ptr;
720 int index;
721#endif
722
723 dir_in = US_DIRECTION(srb->cmd[0]);
724
725 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530726 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000727 result = usb_stor_BBB_comdat(srb, us);
728 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530729 debug("failed to send CBW status %ld\n",
730 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000731 usb_stor_BBB_reset(us);
732 return USB_STOR_TRANSPORT_FAILED;
733 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200734 if (!(us->flags & USB_READY))
735 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000736 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
737 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
738 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000739 data_actlen = 0;
740 /* no data, go immediately to the STATUS phase */
741 if (srb->datalen == 0)
742 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530743 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000744 if (dir_in)
745 pipe = pipein;
746 else
747 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300748
Michael Trimarchi956a4352008-12-10 15:52:06 +0100749 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
750 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000751 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100752 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530753 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000754 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100755 result = usb_stor_BBB_clear_endpt_stall(us,
756 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000757 if (result >= 0)
758 /* continue on to STATUS phase */
759 goto st;
760 }
761 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530762 debug("usb_bulk_msg error status %ld\n",
763 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000764 usb_stor_BBB_reset(us);
765 return USB_STOR_TRANSPORT_FAILED;
766 }
767#ifdef BBB_XPORT_TRACE
768 for (index = 0; index < data_actlen; index++)
769 printf("pdata[%d] %#x ", index, srb->pdata[index]);
770 printf("\n");
771#endif
772 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100773st:
wdenkde887eb2003-09-10 18:20:28 +0000774 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100775again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530776 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530777 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200778 &actlen, USB_CNTL_TIMEOUT*5);
779
wdenkde887eb2003-09-10 18:20:28 +0000780 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100781 if ((result < 0) && (retry < 1) &&
782 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530783 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000784 /* clear the STALL on the endpoint */
785 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
786 if (result >= 0 && (retry++ < 1))
787 /* do a retry */
788 goto again;
789 }
790 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530791 debug("usb_bulk_msg error status %ld\n",
792 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000793 usb_stor_BBB_reset(us);
794 return USB_STOR_TRANSPORT_FAILED;
795 }
796#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530797 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000798 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
799 printf("ptr[%d] %#x ", index, ptr[index]);
800 printf("\n");
801#endif
802 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530803 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000804 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
805 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530806 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530807 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000808 usb_stor_BBB_reset(us);
809 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530810 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530811 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000812 usb_stor_BBB_reset(us);
813 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530814 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530815 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000816 usb_stor_BBB_reset(us);
817 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530818 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530819 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000820 usb_stor_BBB_reset(us);
821 return USB_STOR_TRANSPORT_FAILED;
822 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530823 debug("transferred %dB instead of %ldB\n",
824 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000825 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530826 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530827 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000828 return USB_STOR_TRANSPORT_FAILED;
829 }
830
831 return result;
832}
833
Simon Glass5fb559d2017-06-14 21:28:30 -0600834static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000835{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100836 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600837 struct scsi_cmd *psrb;
838 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100839 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000840
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200841 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100842 status = USB_STOR_TRANSPORT_GOOD;
843 retry = 0;
844 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* issue the command */
846do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530848 debug("command / Data returned %d, status %lX\n",
849 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000850 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100851 if (us->protocol == US_PR_CBI) {
852 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000853 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100854 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530855 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000856 return status;
857 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100858 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
859 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
860 if (!us->ip_data) {
861 /* if the status is good, report it */
862 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530863 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000864 return status;
865 }
866 }
867 }
868 /* do we have to issue an auto request? */
869 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530871 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000872 us->transport_reset(us);
873 return USB_STOR_TRANSPORT_ERROR;
874 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100875 if ((us->protocol == US_PR_CBI) &&
876 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
877 (srb->cmd[0] == SCSI_INQUIRY))) {
878 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530879 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000880 return USB_STOR_TRANSPORT_GOOD;
881 }
882 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100883 memset(&psrb->cmd[0], 0, 12);
884 psrb->cmd[0] = SCSI_REQ_SENSE;
885 psrb->cmd[1] = srb->lun << 5;
886 psrb->cmd[4] = 18;
887 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200888 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100889 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000890 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100891 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530892 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000893 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100894 if (us->protocol == US_PR_CBI)
895 status = usb_stor_CBI_get_status(psrb, us);
896
897 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530898 debug(" AUTO REQUEST ERROR %ld\n",
899 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000900 return USB_STOR_TRANSPORT_ERROR;
901 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530902 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
903 srb->sense_buf[0], srb->sense_buf[2],
904 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000905 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 if ((srb->sense_buf[2] == 0) &&
907 (srb->sense_buf[12] == 0) &&
908 (srb->sense_buf[13] == 0)) {
909 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000910 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 }
912
wdenkaffae2b2002-08-17 09:36:01 +0000913 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914 switch (srb->sense_buf[2]) {
915 case 0x01:
916 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000917 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000918 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100919 case 0x02:
920 /* Not Ready */
921 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
922 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
923 " 0x%02X (NOT READY)\n", srb->cmd[0],
924 srb->sense_buf[0], srb->sense_buf[2],
925 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000926 return USB_STOR_TRANSPORT_FAILED;
927 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000928 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000929 goto do_retry;
930 }
931 break;
932 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100933 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
934 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
935 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
936 srb->sense_buf[2], srb->sense_buf[12],
937 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000938 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100939 } else
wdenkde887eb2003-09-10 18:20:28 +0000940 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000941 break;
wdenkaffae2b2002-08-17 09:36:01 +0000942 }
943 return USB_STOR_TRANSPORT_FAILED;
944}
945
Bin Meng9f447112017-09-07 06:13:21 -0700946static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
947 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700948{
Bin Mengf6e373e2017-09-07 06:13:20 -0700949 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200950 * Limit the total size of a transfer to 120 KB.
951 *
952 * Some devices are known to choke with anything larger. It seems like
953 * the problem stems from the fact that original IDE controllers had
954 * only an 8-bit register to hold the number of sectors in one transfer
955 * and even those couldn't handle a full 256 sectors.
956 *
957 * Because we want to make sure we interoperate with as many devices as
958 * possible, we will maintain a 240 sector transfer size limit for USB
959 * Mass Storage devices.
960 *
961 * Tests show that other operating have similar limits with Microsoft
962 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
963 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
964 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700965 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200966 unsigned short blk = 240;
967
968#if CONFIG_IS_ENABLED(DM_USB)
969 size_t size;
970 int ret;
971
Bin Meng9f447112017-09-07 06:13:21 -0700972 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200973 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700974 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700975#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700976
977 us->max_xfer_blk = blk;
978}
wdenkaffae2b2002-08-17 09:36:01 +0000979
Simon Glass5fb559d2017-06-14 21:28:30 -0600980static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000981{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100982 int retry, i;
983 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000984 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100985 memset(&srb->cmd[0], 0, 12);
986 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200987 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 srb->cmd[4] = 36;
989 srb->datalen = 36;
990 srb->cmdlen = 12;
991 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530992 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100993 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000994 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200995 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000996
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000998 printf("error in inquiry\n");
999 return -1;
1000 }
1001 return 0;
1002}
1003
Simon Glass5fb559d2017-06-14 21:28:30 -06001004static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001005{
1006 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001007
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 ptr = (char *)srb->pdata;
1009 memset(&srb->cmd[0], 0, 12);
1010 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001011 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001012 srb->cmd[4] = 18;
1013 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001014 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001015 srb->cmdlen = 12;
1016 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301017 debug("Request Sense returned %02X %02X %02X\n",
1018 srb->sense_buf[2], srb->sense_buf[12],
1019 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001020 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001021 return 0;
1022}
1023
Simon Glass5fb559d2017-06-14 21:28:30 -06001024static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001025{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001026 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001027
wdenkaffae2b2002-08-17 09:36:01 +00001028 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001029 memset(&srb->cmd[0], 0, 12);
1030 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001031 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001032 srb->datalen = 0;
1033 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001034 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1035 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001036 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001037 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001038 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001039 /*
1040 * Check the Key Code Qualifier, if it matches
1041 * "Not Ready - medium not present"
1042 * (the sense Key equals 0x2 and the ASC is 0x3a)
1043 * return immediately as the medium being absent won't change
1044 * unless there is a user action.
1045 */
1046 if ((srb->sense_buf[2] == 0x02) &&
1047 (srb->sense_buf[12] == 0x3a))
1048 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001049 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001050 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001051
wdenkaffae2b2002-08-17 09:36:01 +00001052 return -1;
1053}
1054
Simon Glass5fb559d2017-06-14 21:28:30 -06001055static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001056{
1057 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001058 /* XXX retries */
1059 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001060 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001061 memset(&srb->cmd[0], 0, 12);
1062 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001063 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001064 srb->datalen = 8;
1065 srb->cmdlen = 12;
1066 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001067 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001068 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001069
wdenkaffae2b2002-08-17 09:36:01 +00001070 return -1;
1071}
1072
Simon Glass5fb559d2017-06-14 21:28:30 -06001073static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1074 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001075{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001076 memset(&srb->cmd[0], 0, 12);
1077 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001078 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001079 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1080 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1081 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1082 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1083 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1084 srb->cmd[8] = (unsigned char) blocks & 0xff;
1085 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301086 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001087 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001088}
1089
Simon Glass5fb559d2017-06-14 21:28:30 -06001090static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1091 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301092{
1093 memset(&srb->cmd[0], 0, 12);
1094 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001095 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301096 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1097 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1098 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1099 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1100 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1101 srb->cmd[8] = (unsigned char) blocks & 0xff;
1102 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301103 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301104 return ss->transport(srb, ss);
1105}
1106
wdenkaffae2b2002-08-17 09:36:01 +00001107
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001108#ifdef CONFIG_USB_BIN_FIXUP
1109/*
1110 * Some USB storage devices queried for SCSI identification data respond with
1111 * binary strings, which if output to the console freeze the terminal. The
1112 * workaround is to modify the vendor and product strings read from such
1113 * device with proper values (as reported by 'usb info').
1114 *
1115 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001116 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001117 */
1118static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1119 unsigned char vendor[],
1120 unsigned char product[]) {
1121 const unsigned char max_vendor_len = 40;
1122 const unsigned char max_product_len = 20;
1123 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001124 strncpy((char *)vendor, "SMSC", max_vendor_len);
1125 strncpy((char *)product, "Flash Media Cntrller",
1126 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001127 }
1128}
1129#endif /* CONFIG_USB_BIN_FIXUP */
1130
Sven Schwermerc58ff202018-11-21 08:43:57 +01001131#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001132static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1133 lbaint_t blkcnt, void *buffer)
1134#else
Simon Glasse3394752016-02-29 15:25:34 -07001135static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001136 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001137#endif
wdenkaffae2b2002-08-17 09:36:01 +00001138{
Gabe Black7d077682012-10-12 14:26:07 +00001139 lbaint_t start, blks;
1140 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001141 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001142 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001143 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001144 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001145 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001146#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001147 struct blk_desc *block_dev;
1148#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001149
1150 if (blkcnt == 0)
1151 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001152 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001153#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001154 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001155 udev = dev_get_parent_priv(dev_get_parent(dev));
1156 debug("\nusb_read: udev %d\n", block_dev->devnum);
1157#else
Simon Glass99e598e2016-02-29 15:25:54 -07001158 debug("\nusb_read: udev %d\n", block_dev->devnum);
1159 udev = usb_dev_desc[block_dev->devnum].priv;
1160 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001161 debug("%s: No device\n", __func__);
1162 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001163 }
Simon Glass01f5be92016-02-29 15:25:58 -07001164#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001165 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001166
1167 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001168 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001169 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001170 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001171 start = blknr;
1172 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001173
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001174 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1175 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001176
wdenkaffae2b2002-08-17 09:36:01 +00001177 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001178 /* XXX need some comment here */
1179 retry = 2;
1180 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001181 if (blks > ss->max_xfer_blk)
1182 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001183 else
1184 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001185retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001186 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001187 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001188 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001189 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001190 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301191 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001192 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001193 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001194 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001195 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001196 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001197 break;
1198 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001199 start += smallblks;
1200 blks -= smallblks;
1201 buf_addr += srb->datalen;
1202 } while (blks != 0);
1203
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001204 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301205 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001206
Marek Vasut118a9032020-04-06 14:29:44 +02001207 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001208 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001209 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001210 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001211 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001212}
1213
Sven Schwermerc58ff202018-11-21 08:43:57 +01001214#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001215static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1216 lbaint_t blkcnt, const void *buffer)
1217#else
Simon Glasse3394752016-02-29 15:25:34 -07001218static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001219 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001220#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301221{
Gabe Black7d077682012-10-12 14:26:07 +00001222 lbaint_t start, blks;
1223 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301224 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001225 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001226 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001227 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001228 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001229#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001230 struct blk_desc *block_dev;
1231#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301232
1233 if (blkcnt == 0)
1234 return 0;
1235
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301236 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001237#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001238 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001239 udev = dev_get_parent_priv(dev_get_parent(dev));
1240 debug("\nusb_read: udev %d\n", block_dev->devnum);
1241#else
Simon Glass99e598e2016-02-29 15:25:54 -07001242 debug("\nusb_read: udev %d\n", block_dev->devnum);
1243 udev = usb_dev_desc[block_dev->devnum].priv;
1244 if (!udev) {
1245 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001246 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001247 }
Simon Glass01f5be92016-02-29 15:25:58 -07001248#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001249 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301250
1251 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001252 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301253
Simon Glass99e598e2016-02-29 15:25:54 -07001254 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001255 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301256 start = blknr;
1257 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301258
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001259 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1260 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301261
1262 do {
1263 /* If write fails retry for max retry count else
1264 * return with number of blocks written successfully.
1265 */
1266 retry = 2;
1267 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001268 if (blks > ss->max_xfer_blk)
1269 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301270 else
1271 smallblks = (unsigned short) blks;
1272retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001273 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301274 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001275 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301276 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001277 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301278 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001279 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001280 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301281 if (retry--)
1282 goto retry_it;
1283 blkcnt -= blks;
1284 break;
1285 }
1286 start += smallblks;
1287 blks -= smallblks;
1288 buf_addr += srb->datalen;
1289 } while (blks != 0);
1290
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001291 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1292 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301293
Marek Vasut118a9032020-04-06 14:29:44 +02001294 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301295 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001296 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001297 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301298 return blkcnt;
1299
1300}
wdenkaffae2b2002-08-17 09:36:01 +00001301
1302/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001303int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1304 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001305{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001306 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001307 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301308 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001309 unsigned int flags = 0;
1310
wdenkaffae2b2002-08-17 09:36:01 +00001311 /* let's examine the device now */
1312 iface = &dev->config.if_desc[ifnum];
1313
wdenkaffae2b2002-08-17 09:36:01 +00001314 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001315 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1316 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1317 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001318 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001319 /* if it's not a mass storage, we go no further */
1320 return 0;
1321 }
1322
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001323 memset(ss, 0, sizeof(struct us_data));
1324
wdenkaffae2b2002-08-17 09:36:01 +00001325 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301326 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001327
1328 /* Initialize the us_data structure with some useful info */
1329 ss->flags = flags;
1330 ss->ifnum = ifnum;
1331 ss->pusb_dev = dev;
1332 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001333 ss->subclass = iface->desc.bInterfaceSubClass;
1334 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001335
1336 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301337 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001338 switch (ss->protocol) {
1339 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301340 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001341 ss->transport = usb_stor_CB_transport;
1342 ss->transport_reset = usb_stor_CB_reset;
1343 break;
1344
1345 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301346 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001347 ss->transport = usb_stor_CB_transport;
1348 ss->transport_reset = usb_stor_CB_reset;
1349 break;
wdenkde887eb2003-09-10 18:20:28 +00001350 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301351 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001352 ss->transport = usb_stor_BBB_transport;
1353 ss->transport_reset = usb_stor_BBB_reset;
1354 break;
wdenkaffae2b2002-08-17 09:36:01 +00001355 default:
wdenk5f495752004-02-26 23:46:20 +00001356 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001357 return 0;
1358 break;
1359 }
1360
1361 /*
1362 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1363 * An optional interrupt is OK (necessary for CBI protocol).
1364 * We will ignore any others.
1365 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001366 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301367 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001368 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301369 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001370 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301371 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1372 ss->ep_in = ep_desc->bEndpointAddress &
1373 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001374 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001375 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301376 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001377 USB_ENDPOINT_NUMBER_MASK;
1378 }
1379
1380 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301381 if ((ep_desc->bmAttributes &
1382 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1383 ss->ep_int = ep_desc->bEndpointAddress &
1384 USB_ENDPOINT_NUMBER_MASK;
1385 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001386 }
1387 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301388 debug("Endpoints In %d Out %d Int %d\n",
1389 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001390
1391 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001392 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001393 !ss->ep_in || !ss->ep_out ||
1394 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301395 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001396 return 0;
1397 }
1398 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001399 /* We only handle certain protocols. Currently, these are
1400 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001401 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001402 */
wdenk5f495752004-02-26 23:46:20 +00001403 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1404 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001405 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001406 return 0;
1407 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001408 if (ss->ep_int) {
1409 /* we had found an interrupt endpoint, prepare irq pipe
1410 * set up the IRQ pipe and handler
1411 */
wdenkaffae2b2002-08-17 09:36:01 +00001412 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1413 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1414 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001415 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001416 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001417
1418 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001419 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001420
Michael Trimarchi956a4352008-12-10 15:52:06 +01001421 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001422 return 1;
1423}
1424
Michael Trimarchi956a4352008-12-10 15:52:06 +01001425int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001426 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001427{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001428 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001429 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1430 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1431 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001432 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001433
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001434 pccb->pdata = usb_stor_buf;
1435
1436 dev_desc->target = dev->devnum;
1437 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301438 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001439
Simon Glass78330d62015-03-25 12:22:12 -06001440 if (usb_inquiry(pccb, ss)) {
1441 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001442 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001443 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001444
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001445 perq = usb_stor_buf[0];
1446 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001447
Soeren Moche4828002014-11-08 07:02:14 +01001448 /*
1449 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1450 * they would not respond to test_unit_ready .
1451 */
1452 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001453 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001454 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001455 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001456 if ((modi&0x80) == 0x80) {
1457 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001458 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001459 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001460 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1461 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1462 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001463 dev_desc->vendor[8] = 0;
1464 dev_desc->product[16] = 0;
1465 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001466#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001467 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1468 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001469#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301470 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1471 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001472 if (usb_test_unit_ready(pccb, ss)) {
1473 printf("Device NOT ready\n"
1474 " Request Sense returned %02X %02X %02X\n",
1475 pccb->sense_buf[2], pccb->sense_buf[12],
1476 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001477 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001478 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001479 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001480 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001481 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001482 memset(pccb->pdata, 0, 8);
1483 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001484 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001485 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001486 cap[0] = 2880;
1487 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001488 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001489 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001490#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001491 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1492 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001493
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001494 cap[0] = cpu_to_be32(cap[0]);
1495 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001496#endif
1497
1498 capacity = be32_to_cpu(cap[0]) + 1;
1499 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001500
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001501 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1502 dev_desc->lba = capacity;
1503 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001504 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001505 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301506 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001507
wdenkaffae2b2002-08-17 09:36:01 +00001508 return 1;
1509}
Simon Glassac9774e2015-03-25 12:22:16 -06001510
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001511#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001512
1513static int usb_mass_storage_probe(struct udevice *dev)
1514{
Simon Glassde44acf2015-09-28 23:32:01 -06001515 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001516 int ret;
1517
1518 usb_disable_asynch(1); /* asynch transfer not allowed */
1519 ret = usb_stor_probe_device(udev);
1520 usb_disable_asynch(0); /* asynch transfer allowed */
1521
1522 return ret;
1523}
1524
1525static const struct udevice_id usb_mass_storage_ids[] = {
1526 { .compatible = "usb-mass-storage" },
1527 { }
1528};
1529
1530U_BOOT_DRIVER(usb_mass_storage) = {
1531 .name = "usb_mass_storage",
1532 .id = UCLASS_MASS_STORAGE,
1533 .of_match = usb_mass_storage_ids,
1534 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001535#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001536 .plat_auto = sizeof(struct us_data),
Simon Glass01f5be92016-02-29 15:25:58 -07001537#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001538};
1539
1540UCLASS_DRIVER(usb_mass_storage) = {
1541 .id = UCLASS_MASS_STORAGE,
1542 .name = "usb_mass_storage",
1543};
1544
1545static const struct usb_device_id mass_storage_id_table[] = {
1546 {
1547 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1548 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1549 },
1550 { } /* Terminating entry */
1551};
1552
Simon Glass46952fb2015-07-06 16:47:51 -06001553U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001554#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001555
Sven Schwermerc58ff202018-11-21 08:43:57 +01001556#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001557static const struct blk_ops usb_storage_ops = {
1558 .read = usb_stor_read,
1559 .write = usb_stor_write,
1560};
1561
1562U_BOOT_DRIVER(usb_storage_blk) = {
1563 .name = "usb_storage_blk",
1564 .id = UCLASS_BLK,
1565 .ops = &usb_storage_ops,
1566};
Simon Glassd3171412016-05-01 11:36:06 -06001567#else
1568U_BOOT_LEGACY_BLK(usb) = {
1569 .if_typename = "usb",
1570 .if_type = IF_TYPE_USB,
1571 .max_devs = USB_MAX_STOR_DEV,
1572 .desc = usb_dev_desc,
1573};
Simon Glassac9774e2015-03-25 12:22:16 -06001574#endif