blob: 946c6b2b323ab62747c82e5d31b5f6b43d62b6ba [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 */
97 unsigned int irqpipe; /* pipe for release_irq */
98 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 }
242 }
243#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700244 /* We don't have space to even probe if we hit the maximum */
245 if (usb_max_devs == USB_MAX_STOR_DEV) {
246 printf("max USB Storage Device reached: %d stopping\n",
247 usb_max_devs);
248 return -ENOSPC;
249 }
250
Simon Glass99e598e2016-02-29 15:25:54 -0700251 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
252 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600253
Simon Glass99e598e2016-02-29 15:25:54 -0700254 /*
255 * OK, it's a storage device. Iterate over its LUNs and populate
256 * usb_dev_desc'
257 */
258 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600259
Simon Glass99e598e2016-02-29 15:25:54 -0700260 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
261 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
262 lun++) {
263 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600264
Simon Glass99e598e2016-02-29 15:25:54 -0700265 blkdev = &usb_dev_desc[usb_max_devs];
266 memset(blkdev, '\0', sizeof(struct blk_desc));
267 blkdev->if_type = IF_TYPE_USB;
268 blkdev->devnum = usb_max_devs;
269 blkdev->part_type = PART_TYPE_UNKNOWN;
270 blkdev->target = 0xff;
271 blkdev->type = DEV_TYPE_UNKNOWN;
272 blkdev->block_read = usb_stor_read;
273 blkdev->block_write = usb_stor_write;
274 blkdev->lun = lun;
275 blkdev->priv = udev;
276
277 if (usb_stor_get_info(udev, &usb_stor[start],
278 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700279 debug("partype: %d\n", blkdev->part_type);
280 part_init(blkdev);
281 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700282 usb_max_devs++;
283 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600284 }
285 }
Simon Glass01f5be92016-02-29 15:25:58 -0700286#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600287
Simon Glassdf7d34f2015-03-25 12:22:15 -0600288 return 0;
289}
290
291void usb_stor_reset(void)
292{
293 usb_max_devs = 0;
294}
295
Michael Trimarchi956a4352008-12-10 15:52:06 +0100296/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200297 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000298 * to the user if mode = 1
299 * returns current device or -1 if no
300 */
301int usb_stor_scan(int mode)
302{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100303 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200304 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100305
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100306#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100307 unsigned char i;
308
wdenkaffae2b2002-08-17 09:36:01 +0000309 usb_disable_asynch(1); /* asynch transfer not allowed */
310
Simon Glassdf7d34f2015-03-25 12:22:15 -0600311 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100312 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600313 struct usb_device *dev;
314
Michael Trimarchi956a4352008-12-10 15:52:06 +0100315 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530316 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600317 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000318 break;
wdenkaffae2b2002-08-17 09:36:01 +0000319 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200320
wdenkaffae2b2002-08-17 09:36:01 +0000321 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100322#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200323 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100324 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000325 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100326 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000327}
328
329static int usb_stor_irq(struct usb_device *dev)
330{
331 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100332 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000333
Michael Trimarchi956a4352008-12-10 15:52:06 +0100334 if (us->ip_wanted)
335 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000336 return 0;
337}
338
339
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530340#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000341
Simon Glass5fb559d2017-06-14 21:28:30 -0600342static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000343{
344 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100345 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
346 for (i = 0; i < 12; i++)
347 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000348 printf("\n");
349}
350
351static void display_int_status(unsigned long tmp)
352{
353 printf("Status: %s %s %s %s %s %s %s\n",
354 (tmp & USB_ST_ACTIVE) ? "Active" : "",
355 (tmp & USB_ST_STALLED) ? "Stalled" : "",
356 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
357 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
358 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
359 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
360 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
361}
362#endif
363/***********************************************************************
364 * Data transfer routines
365 ***********************************************************************/
366
367static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
368{
369 int max_size;
370 int this_xfer;
371 int result;
372 int partial;
373 int maxtry;
374 int stat;
375
376 /* determine the maximum packet size for these transfers */
377 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
378
379 /* while we have data left to transfer */
380 while (length) {
381
382 /* calculate how long this will be -- maximum or a remainder */
383 this_xfer = length > max_size ? max_size : length;
384 length -= this_xfer;
385
386 /* setup the retry counter */
387 maxtry = 10;
388
389 /* set up the transfer loop */
390 do {
391 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600392 debug("Bulk xfer 0x%lx(%d) try #%d\n",
393 (ulong)map_to_sysmem(buf), this_xfer,
394 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000395 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100396 this_xfer, &partial,
397 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530398 debug("bulk_msg returned %d xferred %d/%d\n",
399 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100400 if (us->pusb_dev->status != 0) {
401 /* if we stall, we need to clear it before
402 * we go on
403 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530404#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000405 display_int_status(us->pusb_dev->status);
406#endif
407 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530408 debug("stalled ->clearing endpoint" \
409 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000410 stat = us->pusb_dev->status;
411 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100412 us->pusb_dev->status = stat;
413 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530414 debug("bulk transferred" \
415 "with error %lX," \
416 " but data ok\n",
417 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000418 return 0;
419 }
420 else
421 return result;
422 }
423 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530424 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000425 return result;
426 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530427 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100428 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530429 debug(" %ld, but data ok\n",
430 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000431 return 0;
432 }
433 /* if our try counter reaches 0, bail out */
Michal Simekcfd8a6e2020-12-01 14:02:58 +0100434 debug(" %ld, data %d\n",
435 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000436 if (!maxtry--)
437 return result;
438 }
439 /* update to show what data was transferred */
440 this_xfer -= partial;
441 buf += partial;
442 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100443 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000444 }
445
446 /* if we get here, we're done and successful */
447 return 0;
448}
449
wdenkde887eb2003-09-10 18:20:28 +0000450static int usb_stor_BBB_reset(struct us_data *us)
451{
452 int result;
453 unsigned int pipe;
454
455 /*
456 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
457 *
458 * For Reset Recovery the host shall issue in the following order:
459 * a) a Bulk-Only Mass Storage Reset
460 * b) a Clear Feature HALT to the Bulk-In endpoint
461 * c) a Clear Feature HALT to the Bulk-Out endpoint
462 *
463 * This is done in 3 steps.
464 *
465 * If the reset doesn't succeed, the device should be port reset.
466 *
467 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
468 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530469 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100470 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
471 US_BBB_RESET,
472 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000473 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200474
Michael Trimarchi956a4352008-12-10 15:52:06 +0100475 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530476 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000477 return -1;
478 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200479
wdenkde887eb2003-09-10 18:20:28 +0000480 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000481 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530482 debug("BBB_reset result %d: status %lX reset\n",
483 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000484 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
485 result = usb_clear_halt(us->pusb_dev, pipe);
486 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000487 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530488 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
489 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000490 /* long wait for reset */
491 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
492 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000493 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530494 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
495 result, us->pusb_dev->status);
496 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000497 return 0;
498}
499
wdenkaffae2b2002-08-17 09:36:01 +0000500/* FIXME: this reset function doesn't really reset the port, and it
501 * should. Actually it should probably do what it's doing here, and
502 * reset the port physically
503 */
504static int usb_stor_CB_reset(struct us_data *us)
505{
506 unsigned char cmd[12];
507 int result;
508
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530509 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100510 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000511 cmd[0] = SCSI_SEND_DIAG;
512 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100513 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
514 US_CBI_ADSC,
515 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
516 0, us->ifnum, cmd, sizeof(cmd),
517 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000518
519 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000520 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530521 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
522 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000523 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
524 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
525
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530526 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000527 return 0;
528}
529
wdenkde887eb2003-09-10 18:20:28 +0000530/*
531 * Set up the command for a BBB device. Note that the actual SCSI
532 * command is copied into cbw.CBWCDB.
533 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600534static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000535{
536 int result;
537 int actlen;
538 int dir_in;
539 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600540 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000541
542 dir_in = US_DIRECTION(srb->cmd[0]);
543
544#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530545 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100546 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
547 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000548 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100549 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000550 printf("cmd[%d] %#x ", result, srb->cmd[result]);
551 printf("\n");
552 }
553#endif
554 /* sanity checks */
555 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530556 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000557 return -1;
558 }
559
560 /* always OUT to the ep */
561 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
562
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530563 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
564 cbw->dCBWTag = cpu_to_le32(CBWTag++);
565 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
566 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
567 cbw->bCBWLUN = srb->lun;
568 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000569 /* copy the command data into the CBW command data buffer */
570 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300571
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530572 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
573 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100574 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000575 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530576 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000577 return result;
578}
579
wdenkaffae2b2002-08-17 09:36:01 +0000580/* FIXME: we also need a CBI_command which sets up the completion
581 * interrupt, and waits for it
582 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600583static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000584{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200585 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100586 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000587 unsigned int pipe;
588 unsigned long status;
589
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 retry = 5;
591 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000592
Michael Trimarchi956a4352008-12-10 15:52:06 +0100593 if (dir_in)
594 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
595 else
596 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
597
598 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530599 debug("CBI gets a command: Try %d\n", 5 - retry);
600#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000601 usb_show_srb(srb);
602#endif
603 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100604 result = usb_control_msg(us->pusb_dev,
605 usb_sndctrlpipe(us->pusb_dev , 0),
606 US_CBI_ADSC,
607 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000608 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100609 srb->cmd, srb->cmdlen,
610 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530611 debug("CB_transport: control msg returned %d, status %lX\n",
612 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000613 /* check the return code for the command */
614 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100615 if (us->pusb_dev->status & USB_ST_STALLED) {
616 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530617 debug(" stall during command found," \
618 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100619 usb_clear_halt(us->pusb_dev,
620 usb_sndctrlpipe(us->pusb_dev, 0));
621 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000622 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530623 debug(" error during command %02X" \
624 " Stat = %lX\n", srb->cmd[0],
625 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000626 return result;
627 }
628 /* transfer the data payload for this command, if one exists*/
629
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530630 debug("CB_transport: control msg returned %d," \
631 " direction is %s to go 0x%lx\n", result,
632 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000633 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100634 result = us_one_transfer(us, pipe, (char *)srb->pdata,
635 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530636 debug("CBI attempted to transfer data," \
637 " result is %d status %lX, len %d\n",
638 result, us->pusb_dev->status,
639 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100640 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000641 break;
642 } /* if (srb->datalen) */
643 else
644 break;
645 }
646 /* return result */
647
648 return result;
649}
650
651
Simon Glass5fb559d2017-06-14 21:28:30 -0600652static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000653{
654 int timeout;
655
wdenk5f495752004-02-26 23:46:20 +0000656 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200657 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200658 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000659 timeout = 1000;
660 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300661 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000662 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000663 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000664 }
665 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100666 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000667 us->ip_wanted = 0;
668 return USB_STOR_TRANSPORT_ERROR;
669 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700670 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530671 us->ip_data, us->pusb_dev->irq_act_len,
672 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000673 /* UFI gives us ASC and ASCQ, like a request sense */
674 if (us->subclass == US_SC_UFI) {
675 if (srb->cmd[0] == SCSI_REQ_SENSE ||
676 srb->cmd[0] == SCSI_INQUIRY)
677 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000678 else if (us->ip_data)
679 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000680 else
wdenk5f495752004-02-26 23:46:20 +0000681 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000682 }
683 /* otherwise, we interpret the data normally */
684 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000685 case 0x0001:
686 return USB_STOR_TRANSPORT_GOOD;
687 case 0x0002:
688 return USB_STOR_TRANSPORT_FAILED;
689 default:
690 return USB_STOR_TRANSPORT_ERROR;
691 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000692 return USB_STOR_TRANSPORT_ERROR;
693}
694
695#define USB_TRANSPORT_UNKNOWN_RETRY 5
696#define USB_TRANSPORT_NOT_READY_RETRY 10
697
wdenkde887eb2003-09-10 18:20:28 +0000698/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000699static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000700{
wdenkde887eb2003-09-10 18:20:28 +0000701 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900702 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
703 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
704 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000705}
706
Simon Glass5fb559d2017-06-14 21:28:30 -0600707static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000708{
709 int result, retry;
710 int dir_in;
711 int actlen, data_actlen;
712 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600713 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000714#ifdef BBB_XPORT_TRACE
715 unsigned char *ptr;
716 int index;
717#endif
718
719 dir_in = US_DIRECTION(srb->cmd[0]);
720
721 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530722 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000723 result = usb_stor_BBB_comdat(srb, us);
724 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530725 debug("failed to send CBW status %ld\n",
726 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000727 usb_stor_BBB_reset(us);
728 return USB_STOR_TRANSPORT_FAILED;
729 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200730 if (!(us->flags & USB_READY))
731 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000732 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
733 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
734 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000735 data_actlen = 0;
736 /* no data, go immediately to the STATUS phase */
737 if (srb->datalen == 0)
738 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530739 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000740 if (dir_in)
741 pipe = pipein;
742 else
743 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300744
Michael Trimarchi956a4352008-12-10 15:52:06 +0100745 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
746 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000747 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100748 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530749 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000750 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100751 result = usb_stor_BBB_clear_endpt_stall(us,
752 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000753 if (result >= 0)
754 /* continue on to STATUS phase */
755 goto st;
756 }
757 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530758 debug("usb_bulk_msg error status %ld\n",
759 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000760 usb_stor_BBB_reset(us);
761 return USB_STOR_TRANSPORT_FAILED;
762 }
763#ifdef BBB_XPORT_TRACE
764 for (index = 0; index < data_actlen; index++)
765 printf("pdata[%d] %#x ", index, srb->pdata[index]);
766 printf("\n");
767#endif
768 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100769st:
wdenkde887eb2003-09-10 18:20:28 +0000770 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100771again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530772 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530773 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200774 &actlen, USB_CNTL_TIMEOUT*5);
775
wdenkde887eb2003-09-10 18:20:28 +0000776 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100777 if ((result < 0) && (retry < 1) &&
778 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530779 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000780 /* clear the STALL on the endpoint */
781 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
782 if (result >= 0 && (retry++ < 1))
783 /* do a retry */
784 goto again;
785 }
786 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530787 debug("usb_bulk_msg error status %ld\n",
788 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000789 usb_stor_BBB_reset(us);
790 return USB_STOR_TRANSPORT_FAILED;
791 }
792#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530793 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000794 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
795 printf("ptr[%d] %#x ", index, ptr[index]);
796 printf("\n");
797#endif
798 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530799 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000800 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
801 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530802 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530803 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000804 usb_stor_BBB_reset(us);
805 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530806 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530807 debug("!Tag\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 (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530811 debug(">PHASE\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;
818 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530819 debug("transferred %dB instead of %ldB\n",
820 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000821 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530822 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530823 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000824 return USB_STOR_TRANSPORT_FAILED;
825 }
826
827 return result;
828}
829
Simon Glass5fb559d2017-06-14 21:28:30 -0600830static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000831{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100832 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600833 struct scsi_cmd *psrb;
834 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100835 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000836
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200837 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100838 status = USB_STOR_TRANSPORT_GOOD;
839 retry = 0;
840 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000841 /* issue the command */
842do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100843 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530844 debug("command / Data returned %d, status %lX\n",
845 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000846 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 if (us->protocol == US_PR_CBI) {
848 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000849 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100850 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530851 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000852 return status;
853 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100854 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
855 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
856 if (!us->ip_data) {
857 /* if the status is good, report it */
858 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530859 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000860 return status;
861 }
862 }
863 }
864 /* do we have to issue an auto request? */
865 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100866 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530867 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000868 us->transport_reset(us);
869 return USB_STOR_TRANSPORT_ERROR;
870 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100871 if ((us->protocol == US_PR_CBI) &&
872 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
873 (srb->cmd[0] == SCSI_INQUIRY))) {
874 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530875 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000876 return USB_STOR_TRANSPORT_GOOD;
877 }
878 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100879 memset(&psrb->cmd[0], 0, 12);
880 psrb->cmd[0] = SCSI_REQ_SENSE;
881 psrb->cmd[1] = srb->lun << 5;
882 psrb->cmd[4] = 18;
883 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200884 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100885 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000886 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100887 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530888 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000889 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100890 if (us->protocol == US_PR_CBI)
891 status = usb_stor_CBI_get_status(psrb, us);
892
893 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530894 debug(" AUTO REQUEST ERROR %ld\n",
895 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000896 return USB_STOR_TRANSPORT_ERROR;
897 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530898 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
899 srb->sense_buf[0], srb->sense_buf[2],
900 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000901 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100902 if ((srb->sense_buf[2] == 0) &&
903 (srb->sense_buf[12] == 0) &&
904 (srb->sense_buf[13] == 0)) {
905 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000906 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100907 }
908
wdenkaffae2b2002-08-17 09:36:01 +0000909 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100910 switch (srb->sense_buf[2]) {
911 case 0x01:
912 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000913 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000914 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100915 case 0x02:
916 /* Not Ready */
917 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
918 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
919 " 0x%02X (NOT READY)\n", srb->cmd[0],
920 srb->sense_buf[0], srb->sense_buf[2],
921 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000922 return USB_STOR_TRANSPORT_FAILED;
923 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000924 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000925 goto do_retry;
926 }
927 break;
928 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100929 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
930 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
931 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
932 srb->sense_buf[2], srb->sense_buf[12],
933 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000934 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100935 } else
wdenkde887eb2003-09-10 18:20:28 +0000936 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000937 break;
wdenkaffae2b2002-08-17 09:36:01 +0000938 }
939 return USB_STOR_TRANSPORT_FAILED;
940}
941
Bin Meng9f447112017-09-07 06:13:21 -0700942static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
943 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700944{
Bin Mengf6e373e2017-09-07 06:13:20 -0700945 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200946 * Limit the total size of a transfer to 120 KB.
947 *
948 * Some devices are known to choke with anything larger. It seems like
949 * the problem stems from the fact that original IDE controllers had
950 * only an 8-bit register to hold the number of sectors in one transfer
951 * and even those couldn't handle a full 256 sectors.
952 *
953 * Because we want to make sure we interoperate with as many devices as
954 * possible, we will maintain a 240 sector transfer size limit for USB
955 * Mass Storage devices.
956 *
957 * Tests show that other operating have similar limits with Microsoft
958 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
959 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
960 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700961 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200962 unsigned short blk = 240;
963
964#if CONFIG_IS_ENABLED(DM_USB)
965 size_t size;
966 int ret;
967
Bin Meng9f447112017-09-07 06:13:21 -0700968 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200969 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700970 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700971#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700972
973 us->max_xfer_blk = blk;
974}
wdenkaffae2b2002-08-17 09:36:01 +0000975
Simon Glass5fb559d2017-06-14 21:28:30 -0600976static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000977{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978 int retry, i;
979 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000980 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 memset(&srb->cmd[0], 0, 12);
982 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200983 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100984 srb->cmd[4] = 36;
985 srb->datalen = 36;
986 srb->cmdlen = 12;
987 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530988 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100989 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000990 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200991 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000992
Michael Trimarchi956a4352008-12-10 15:52:06 +0100993 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000994 printf("error in inquiry\n");
995 return -1;
996 }
997 return 0;
998}
999
Simon Glass5fb559d2017-06-14 21:28:30 -06001000static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001001{
1002 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001003
Michael Trimarchi956a4352008-12-10 15:52:06 +01001004 ptr = (char *)srb->pdata;
1005 memset(&srb->cmd[0], 0, 12);
1006 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001007 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 srb->cmd[4] = 18;
1009 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001010 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001011 srb->cmdlen = 12;
1012 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301013 debug("Request Sense returned %02X %02X %02X\n",
1014 srb->sense_buf[2], srb->sense_buf[12],
1015 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001016 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001017 return 0;
1018}
1019
Simon Glass5fb559d2017-06-14 21:28:30 -06001020static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001021{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001022 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001023
wdenkaffae2b2002-08-17 09:36:01 +00001024 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001025 memset(&srb->cmd[0], 0, 12);
1026 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001027 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001028 srb->datalen = 0;
1029 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001030 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1031 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001032 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001033 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001034 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001035 /*
1036 * Check the Key Code Qualifier, if it matches
1037 * "Not Ready - medium not present"
1038 * (the sense Key equals 0x2 and the ASC is 0x3a)
1039 * return immediately as the medium being absent won't change
1040 * unless there is a user action.
1041 */
1042 if ((srb->sense_buf[2] == 0x02) &&
1043 (srb->sense_buf[12] == 0x3a))
1044 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001045 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001046 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001047
wdenkaffae2b2002-08-17 09:36:01 +00001048 return -1;
1049}
1050
Simon Glass5fb559d2017-06-14 21:28:30 -06001051static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001052{
1053 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001054 /* XXX retries */
1055 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001056 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001057 memset(&srb->cmd[0], 0, 12);
1058 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001059 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001060 srb->datalen = 8;
1061 srb->cmdlen = 12;
1062 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001063 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001064 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001065
wdenkaffae2b2002-08-17 09:36:01 +00001066 return -1;
1067}
1068
Simon Glass5fb559d2017-06-14 21:28:30 -06001069static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1070 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001071{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072 memset(&srb->cmd[0], 0, 12);
1073 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001074 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001075 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 Gautamf94c95d2013-04-12 16:34:33 +05301082 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001083 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001084}
1085
Simon Glass5fb559d2017-06-14 21:28:30 -06001086static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1087 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301088{
1089 memset(&srb->cmd[0], 0, 12);
1090 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001091 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301092 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1093 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1094 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1095 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1096 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1097 srb->cmd[8] = (unsigned char) blocks & 0xff;
1098 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301099 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301100 return ss->transport(srb, ss);
1101}
1102
wdenkaffae2b2002-08-17 09:36:01 +00001103
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001104#ifdef CONFIG_USB_BIN_FIXUP
1105/*
1106 * Some USB storage devices queried for SCSI identification data respond with
1107 * binary strings, which if output to the console freeze the terminal. The
1108 * workaround is to modify the vendor and product strings read from such
1109 * device with proper values (as reported by 'usb info').
1110 *
1111 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001112 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001113 */
1114static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1115 unsigned char vendor[],
1116 unsigned char product[]) {
1117 const unsigned char max_vendor_len = 40;
1118 const unsigned char max_product_len = 20;
1119 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001120 strncpy((char *)vendor, "SMSC", max_vendor_len);
1121 strncpy((char *)product, "Flash Media Cntrller",
1122 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001123 }
1124}
1125#endif /* CONFIG_USB_BIN_FIXUP */
1126
Sven Schwermerc58ff202018-11-21 08:43:57 +01001127#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001128static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1129 lbaint_t blkcnt, void *buffer)
1130#else
Simon Glasse3394752016-02-29 15:25:34 -07001131static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001132 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001133#endif
wdenkaffae2b2002-08-17 09:36:01 +00001134{
Gabe Black7d077682012-10-12 14:26:07 +00001135 lbaint_t start, blks;
1136 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001137 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001138 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001139 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001140 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001141 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001142#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001143 struct blk_desc *block_dev;
1144#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001145
1146 if (blkcnt == 0)
1147 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001148 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001149#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001150 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001151 udev = dev_get_parent_priv(dev_get_parent(dev));
1152 debug("\nusb_read: udev %d\n", block_dev->devnum);
1153#else
Simon Glass99e598e2016-02-29 15:25:54 -07001154 debug("\nusb_read: udev %d\n", block_dev->devnum);
1155 udev = usb_dev_desc[block_dev->devnum].priv;
1156 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001157 debug("%s: No device\n", __func__);
1158 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001159 }
Simon Glass01f5be92016-02-29 15:25:58 -07001160#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001161 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001162
1163 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001164 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001165 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001166 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001167 start = blknr;
1168 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001169
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001170 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1171 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001172
wdenkaffae2b2002-08-17 09:36:01 +00001173 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001174 /* XXX need some comment here */
1175 retry = 2;
1176 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001177 if (blks > ss->max_xfer_blk)
1178 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001179 else
1180 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001181retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001182 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001183 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001184 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001185 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001186 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301187 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001188 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001189 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001190 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001191 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001192 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001193 break;
1194 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001195 start += smallblks;
1196 blks -= smallblks;
1197 buf_addr += srb->datalen;
1198 } while (blks != 0);
1199
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001200 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301201 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001202
Marek Vasut118a9032020-04-06 14:29:44 +02001203 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001204 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001205 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001206 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001207 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001208}
1209
Sven Schwermerc58ff202018-11-21 08:43:57 +01001210#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001211static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1212 lbaint_t blkcnt, const void *buffer)
1213#else
Simon Glasse3394752016-02-29 15:25:34 -07001214static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001215 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001216#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301217{
Gabe Black7d077682012-10-12 14:26:07 +00001218 lbaint_t start, blks;
1219 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301220 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001221 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001222 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001223 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001224 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001225#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001226 struct blk_desc *block_dev;
1227#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301228
1229 if (blkcnt == 0)
1230 return 0;
1231
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301232 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001233#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001234 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001235 udev = dev_get_parent_priv(dev_get_parent(dev));
1236 debug("\nusb_read: udev %d\n", block_dev->devnum);
1237#else
Simon Glass99e598e2016-02-29 15:25:54 -07001238 debug("\nusb_read: udev %d\n", block_dev->devnum);
1239 udev = usb_dev_desc[block_dev->devnum].priv;
1240 if (!udev) {
1241 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001242 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001243 }
Simon Glass01f5be92016-02-29 15:25:58 -07001244#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001245 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301246
1247 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001248 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301249
Simon Glass99e598e2016-02-29 15:25:54 -07001250 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001251 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301252 start = blknr;
1253 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301254
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001255 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1256 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301257
1258 do {
1259 /* If write fails retry for max retry count else
1260 * return with number of blocks written successfully.
1261 */
1262 retry = 2;
1263 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001264 if (blks > ss->max_xfer_blk)
1265 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301266 else
1267 smallblks = (unsigned short) blks;
1268retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001269 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301270 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001271 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301272 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001273 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301274 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001275 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001276 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301277 if (retry--)
1278 goto retry_it;
1279 blkcnt -= blks;
1280 break;
1281 }
1282 start += smallblks;
1283 blks -= smallblks;
1284 buf_addr += srb->datalen;
1285 } while (blks != 0);
1286
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001287 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1288 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301289
Marek Vasut118a9032020-04-06 14:29:44 +02001290 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301291 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001292 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001293 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301294 return blkcnt;
1295
1296}
wdenkaffae2b2002-08-17 09:36:01 +00001297
1298/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001299int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1300 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001301{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001302 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001303 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301304 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001305 unsigned int flags = 0;
1306
wdenkaffae2b2002-08-17 09:36:01 +00001307 /* let's examine the device now */
1308 iface = &dev->config.if_desc[ifnum];
1309
wdenkaffae2b2002-08-17 09:36:01 +00001310 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001311 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1312 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1313 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001314 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001315 /* if it's not a mass storage, we go no further */
1316 return 0;
1317 }
1318
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001319 memset(ss, 0, sizeof(struct us_data));
1320
wdenkaffae2b2002-08-17 09:36:01 +00001321 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301322 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001323
1324 /* Initialize the us_data structure with some useful info */
1325 ss->flags = flags;
1326 ss->ifnum = ifnum;
1327 ss->pusb_dev = dev;
1328 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001329 ss->subclass = iface->desc.bInterfaceSubClass;
1330 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001331
1332 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301333 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001334 switch (ss->protocol) {
1335 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301336 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001337 ss->transport = usb_stor_CB_transport;
1338 ss->transport_reset = usb_stor_CB_reset;
1339 break;
1340
1341 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301342 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001343 ss->transport = usb_stor_CB_transport;
1344 ss->transport_reset = usb_stor_CB_reset;
1345 break;
wdenkde887eb2003-09-10 18:20:28 +00001346 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301347 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001348 ss->transport = usb_stor_BBB_transport;
1349 ss->transport_reset = usb_stor_BBB_reset;
1350 break;
wdenkaffae2b2002-08-17 09:36:01 +00001351 default:
wdenk5f495752004-02-26 23:46:20 +00001352 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001353 return 0;
1354 break;
1355 }
1356
1357 /*
1358 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1359 * An optional interrupt is OK (necessary for CBI protocol).
1360 * We will ignore any others.
1361 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001362 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301363 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001364 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301365 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001366 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301367 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1368 ss->ep_in = ep_desc->bEndpointAddress &
1369 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001370 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001371 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301372 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001373 USB_ENDPOINT_NUMBER_MASK;
1374 }
1375
1376 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301377 if ((ep_desc->bmAttributes &
1378 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1379 ss->ep_int = ep_desc->bEndpointAddress &
1380 USB_ENDPOINT_NUMBER_MASK;
1381 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001382 }
1383 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301384 debug("Endpoints In %d Out %d Int %d\n",
1385 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001386
1387 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001388 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001389 !ss->ep_in || !ss->ep_out ||
1390 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301391 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001392 return 0;
1393 }
1394 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001395 /* We only handle certain protocols. Currently, these are
1396 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001397 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001398 */
wdenk5f495752004-02-26 23:46:20 +00001399 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1400 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001401 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001402 return 0;
1403 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001404 if (ss->ep_int) {
1405 /* we had found an interrupt endpoint, prepare irq pipe
1406 * set up the IRQ pipe and handler
1407 */
wdenkaffae2b2002-08-17 09:36:01 +00001408 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1409 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1410 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001411 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001412 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001413
1414 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001415 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001416
Michael Trimarchi956a4352008-12-10 15:52:06 +01001417 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001418 return 1;
1419}
1420
Michael Trimarchi956a4352008-12-10 15:52:06 +01001421int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001422 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001423{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001424 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001425 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1426 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1427 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001428 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001429
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001430 pccb->pdata = usb_stor_buf;
1431
1432 dev_desc->target = dev->devnum;
1433 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301434 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001435
Simon Glass78330d62015-03-25 12:22:12 -06001436 if (usb_inquiry(pccb, ss)) {
1437 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001438 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001439 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001440
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001441 perq = usb_stor_buf[0];
1442 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001443
Soeren Moche4828002014-11-08 07:02:14 +01001444 /*
1445 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1446 * they would not respond to test_unit_ready .
1447 */
1448 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001449 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001450 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001451 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001452 if ((modi&0x80) == 0x80) {
1453 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001454 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001455 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001456 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1457 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1458 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001459 dev_desc->vendor[8] = 0;
1460 dev_desc->product[16] = 0;
1461 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001462#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001463 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1464 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001465#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301466 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1467 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001468 if (usb_test_unit_ready(pccb, ss)) {
1469 printf("Device NOT ready\n"
1470 " Request Sense returned %02X %02X %02X\n",
1471 pccb->sense_buf[2], pccb->sense_buf[12],
1472 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001473 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001474 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001475 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001476 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001477 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001478 memset(pccb->pdata, 0, 8);
1479 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001480 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001481 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001482 cap[0] = 2880;
1483 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001484 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001485 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001486#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001487 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1488 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001489
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001490 cap[0] = cpu_to_be32(cap[0]);
1491 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001492#endif
1493
1494 capacity = be32_to_cpu(cap[0]) + 1;
1495 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001496
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001497 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1498 dev_desc->lba = capacity;
1499 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001500 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001501 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301502 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001503
wdenkaffae2b2002-08-17 09:36:01 +00001504 return 1;
1505}
Simon Glassac9774e2015-03-25 12:22:16 -06001506
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001507#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001508
1509static int usb_mass_storage_probe(struct udevice *dev)
1510{
Simon Glassde44acf2015-09-28 23:32:01 -06001511 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001512 int ret;
1513
1514 usb_disable_asynch(1); /* asynch transfer not allowed */
1515 ret = usb_stor_probe_device(udev);
1516 usb_disable_asynch(0); /* asynch transfer allowed */
1517
1518 return ret;
1519}
1520
1521static const struct udevice_id usb_mass_storage_ids[] = {
1522 { .compatible = "usb-mass-storage" },
1523 { }
1524};
1525
1526U_BOOT_DRIVER(usb_mass_storage) = {
1527 .name = "usb_mass_storage",
1528 .id = UCLASS_MASS_STORAGE,
1529 .of_match = usb_mass_storage_ids,
1530 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001531#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001532 .plat_auto = sizeof(struct us_data),
Simon Glass01f5be92016-02-29 15:25:58 -07001533#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001534};
1535
1536UCLASS_DRIVER(usb_mass_storage) = {
1537 .id = UCLASS_MASS_STORAGE,
1538 .name = "usb_mass_storage",
1539};
1540
1541static const struct usb_device_id mass_storage_id_table[] = {
1542 {
1543 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1544 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1545 },
1546 { } /* Terminating entry */
1547};
1548
Simon Glass46952fb2015-07-06 16:47:51 -06001549U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001550#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001551
Sven Schwermerc58ff202018-11-21 08:43:57 +01001552#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001553static const struct blk_ops usb_storage_ops = {
1554 .read = usb_stor_read,
1555 .write = usb_stor_write,
1556};
1557
1558U_BOOT_DRIVER(usb_storage_blk) = {
1559 .name = "usb_storage_blk",
1560 .id = UCLASS_BLK,
1561 .ops = &usb_storage_ops,
1562};
Simon Glassd3171412016-05-01 11:36:06 -06001563#else
1564U_BOOT_LEGACY_BLK(usb) = {
1565 .if_typename = "usb",
1566 .if_type = IF_TYPE_USB,
1567 .max_devs = USB_MAX_STOR_DEV,
1568 .desc = usb_dev_desc,
1569};
Simon Glassac9774e2015-03-25 12:22:16 -06001570#endif