blob: a79ed2e23a441d6df3759349b040ee20a9212a90 [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
Simon Glass655306c2020-05-10 11:39:58 -060035#include <blk.h>
Simon Glasse1917ef2022-04-24 23:31:23 -060036#include <bootdev.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 */
Hector Martin7b3d10d2023-10-29 16:23:30 +0900104 bool cmd12; /* use 12-byte commands (RBC/UFI) */
wdenkaffae2b2002-08-17 09:36:01 +0000105};
106
Sven Schwermerc58ff202018-11-21 08:43:57 +0100107#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000108static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700109#endif
wdenkaffae2b2002-08-17 09:36:01 +0000110
wdenk5f495752004-02-26 23:46:20 +0000111#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000112#define USB_STOR_TRANSPORT_FAILED -1
113#define USB_STOR_TRANSPORT_ERROR -2
114
Michael Trimarchi956a4352008-12-10 15:52:06 +0100115int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700116 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100117int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
118 struct us_data *ss);
Sven Schwermerc58ff202018-11-21 08:43:57 +0100119#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700120static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
121 lbaint_t blkcnt, void *buffer);
122static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
123 lbaint_t blkcnt, const void *buffer);
124#else
Simon Glasse3394752016-02-29 15:25:34 -0700125static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700126 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700127static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700128 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700129#endif
wdenkaffae2b2002-08-17 09:36:01 +0000130void uhci_show_temp_int_td(void);
131
Kim Phillipsb052b602012-10-29 13:34:32 +0000132static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000133{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200134 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000135}
136
Michael Trimarchi956a4352008-12-10 15:52:06 +0100137/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200138 * show info on storage devices; 'usb start/init' must be invoked earlier
139 * as we only retrieve structures populated during devices initialization
140 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100141int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200142{
Simon Glass99e598e2016-02-29 15:25:54 -0700143 int count = 0;
Sven Schwermerc58ff202018-11-21 08:43:57 +0100144#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700145 struct udevice *dev;
146
Simon Glassdbfa32c2022-08-11 19:34:59 -0600147 for (blk_first_device(UCLASS_USB, &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700148 dev;
149 blk_next_device(&dev)) {
Simon Glass71fa5b42020-12-03 16:55:18 -0700150 struct blk_desc *desc = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700151
152 printf(" Device %d: ", desc->devnum);
153 dev_print(desc);
154 count++;
155 }
156#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200157 int i;
158
Aras Vaichas7ede1862008-03-25 12:09:07 +1100159 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200160 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100161 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200162 dev_print(&usb_dev_desc[i]);
163 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100164 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100165 }
Simon Glass01f5be92016-02-29 15:25:58 -0700166#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700167 if (!count) {
168 printf("No storage devices, perhaps not 'usb start'ed..?\n");
169 return 1;
170 }
171
Simon Glass8c6c0742016-03-16 07:45:44 -0600172 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200173}
174
Ludovic Courtès134396c2010-10-05 22:04:26 +0200175static unsigned int usb_get_max_lun(struct us_data *us)
176{
177 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530178 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200179 len = usb_control_msg(us->pusb_dev,
180 usb_rcvctrlpipe(us->pusb_dev, 0),
181 US_BBB_GET_MAX_LUN,
182 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
183 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530184 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200185 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530186 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530187 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200188}
189
Simon Glass99e598e2016-02-29 15:25:54 -0700190static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600191{
Simon Glass99e598e2016-02-29 15:25:54 -0700192 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700193
Sven Schwermerc58ff202018-11-21 08:43:57 +0100194#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700195 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700196 int ret;
197#else
Simon Glass99e598e2016-02-29 15:25:54 -0700198 int start;
199
200 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600201 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700202#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600203
Simon Glass01f5be92016-02-29 15:25:58 -0700204 debug("\n\nProbing for storage\n");
Sven Schwermerc58ff202018-11-21 08:43:57 +0100205#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700206 /*
Simon Glass71fa5b42020-12-03 16:55:18 -0700207 * We store the us_data in the mass storage device's plat. It
Simon Glass01f5be92016-02-29 15:25:58 -0700208 * is shared by all LUNs (block devices) attached to this mass storage
209 * device.
210 */
Simon Glassfa20e932020-12-03 16:55:20 -0700211 data = dev_get_plat(udev->dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700212 if (!usb_storage_probe(udev, 0, data))
213 return 0;
214 max_lun = usb_get_max_lun(data);
215 for (lun = 0; lun <= max_lun; lun++) {
216 struct blk_desc *blkdev;
217 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600218 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700219
Simon Glass966b6952016-05-01 11:36:29 -0600220 snprintf(str, sizeof(str), "lun%d", lun);
221 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
Bin Meng2294ecb2023-09-26 16:43:31 +0800222 UCLASS_USB, usb_max_devs,
223 DEFAULT_BLKSZ, 0, &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700224 if (ret) {
225 debug("Cannot bind driver\n");
226 return ret;
227 }
228
Simon Glass71fa5b42020-12-03 16:55:18 -0700229 blkdev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700230 blkdev->target = 0xff;
231 blkdev->lun = lun;
232
233 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengcbc3da82018-10-15 02:21:07 -0700234 if (ret == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700235 usb_max_devs++;
236 debug("%s: Found device %p\n", __func__, udev);
237 } else {
238 debug("usb_stor_get_info: Invalid device\n");
239 ret = device_unbind(dev);
240 if (ret)
241 return ret;
Janne Grunau96c2d112022-11-04 08:38:59 +0100242 continue;
Simon Glass01f5be92016-02-29 15:25:58 -0700243 }
AKASHI Takahirof9c3cc82022-03-08 20:36:40 +0900244
245 ret = blk_probe_or_unbind(dev);
246 if (ret)
247 return ret;
Simon Glasse1917ef2022-04-24 23:31:23 -0600248
Simon Glassb1d581d2023-07-30 11:15:14 -0600249 ret = bootdev_setup_for_sibling_blk(dev, "usb_bootdev");
Simon Glasse1917ef2022-04-24 23:31:23 -0600250 if (ret) {
251 int ret2;
252
253 ret2 = device_unbind(dev);
254 if (ret2)
255 return log_msg_ret("bootdev", ret2);
256 return log_msg_ret("bootdev", ret);
257 }
Simon Glass01f5be92016-02-29 15:25:58 -0700258 }
259#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700260 /* We don't have space to even probe if we hit the maximum */
261 if (usb_max_devs == USB_MAX_STOR_DEV) {
262 printf("max USB Storage Device reached: %d stopping\n",
263 usb_max_devs);
264 return -ENOSPC;
265 }
266
Simon Glass99e598e2016-02-29 15:25:54 -0700267 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
268 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600269
Simon Glass99e598e2016-02-29 15:25:54 -0700270 /*
271 * OK, it's a storage device. Iterate over its LUNs and populate
272 * usb_dev_desc'
273 */
274 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600275
Simon Glass99e598e2016-02-29 15:25:54 -0700276 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
277 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
278 lun++) {
279 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600280
Simon Glass99e598e2016-02-29 15:25:54 -0700281 blkdev = &usb_dev_desc[usb_max_devs];
282 memset(blkdev, '\0', sizeof(struct blk_desc));
Simon Glassfada3f92022-09-17 09:00:09 -0600283 blkdev->uclass_id = UCLASS_USB;
Simon Glass99e598e2016-02-29 15:25:54 -0700284 blkdev->devnum = usb_max_devs;
285 blkdev->part_type = PART_TYPE_UNKNOWN;
286 blkdev->target = 0xff;
287 blkdev->type = DEV_TYPE_UNKNOWN;
288 blkdev->block_read = usb_stor_read;
289 blkdev->block_write = usb_stor_write;
290 blkdev->lun = lun;
291 blkdev->priv = udev;
292
293 if (usb_stor_get_info(udev, &usb_stor[start],
294 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700295 debug("partype: %d\n", blkdev->part_type);
296 part_init(blkdev);
297 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700298 usb_max_devs++;
299 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600300 }
301 }
Simon Glass01f5be92016-02-29 15:25:58 -0700302#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600303
Simon Glassdf7d34f2015-03-25 12:22:15 -0600304 return 0;
305}
306
307void usb_stor_reset(void)
308{
309 usb_max_devs = 0;
310}
311
Michael Trimarchi956a4352008-12-10 15:52:06 +0100312/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200313 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000314 * to the user if mode = 1
315 * returns current device or -1 if no
316 */
317int usb_stor_scan(int mode)
318{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100319 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200320 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100321
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100322#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100323 unsigned char i;
324
wdenkaffae2b2002-08-17 09:36:01 +0000325 usb_disable_asynch(1); /* asynch transfer not allowed */
326
Simon Glassdf7d34f2015-03-25 12:22:15 -0600327 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100328 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600329 struct usb_device *dev;
330
Michael Trimarchi956a4352008-12-10 15:52:06 +0100331 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530332 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600333 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000334 break;
wdenkaffae2b2002-08-17 09:36:01 +0000335 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200336
wdenkaffae2b2002-08-17 09:36:01 +0000337 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100338#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200339 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100340 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000341 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100342 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000343}
344
345static int usb_stor_irq(struct usb_device *dev)
346{
347 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100348 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000349
Michael Trimarchi956a4352008-12-10 15:52:06 +0100350 if (us->ip_wanted)
351 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000352 return 0;
353}
354
355
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530356#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000357
Simon Glass5fb559d2017-06-14 21:28:30 -0600358static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000359{
360 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100361 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
Hector Martin7b3d10d2023-10-29 16:23:30 +0900362 for (i = 0; i < pccb->cmdlen; i++)
Michael Trimarchi956a4352008-12-10 15:52:06 +0100363 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000364 printf("\n");
365}
366
367static void display_int_status(unsigned long tmp)
368{
369 printf("Status: %s %s %s %s %s %s %s\n",
370 (tmp & USB_ST_ACTIVE) ? "Active" : "",
371 (tmp & USB_ST_STALLED) ? "Stalled" : "",
372 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
373 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
374 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
375 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
376 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
377}
378#endif
379/***********************************************************************
380 * Data transfer routines
381 ***********************************************************************/
382
383static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
384{
385 int max_size;
386 int this_xfer;
387 int result;
388 int partial;
389 int maxtry;
390 int stat;
391
392 /* determine the maximum packet size for these transfers */
393 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
394
395 /* while we have data left to transfer */
396 while (length) {
397
398 /* calculate how long this will be -- maximum or a remainder */
399 this_xfer = length > max_size ? max_size : length;
400 length -= this_xfer;
401
402 /* setup the retry counter */
403 maxtry = 10;
404
405 /* set up the transfer loop */
406 do {
407 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600408 debug("Bulk xfer 0x%lx(%d) try #%d\n",
409 (ulong)map_to_sysmem(buf), this_xfer,
410 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000411 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100412 this_xfer, &partial,
413 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530414 debug("bulk_msg returned %d xferred %d/%d\n",
415 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100416 if (us->pusb_dev->status != 0) {
417 /* if we stall, we need to clear it before
418 * we go on
419 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530420#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000421 display_int_status(us->pusb_dev->status);
422#endif
423 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530424 debug("stalled ->clearing endpoint" \
425 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000426 stat = us->pusb_dev->status;
427 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100428 us->pusb_dev->status = stat;
429 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530430 debug("bulk transferred" \
431 "with error %lX," \
432 " but data ok\n",
433 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000434 return 0;
435 }
436 else
437 return result;
438 }
439 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530440 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000441 return result;
442 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530443 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100444 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530445 debug(" %ld, but data ok\n",
446 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000447 return 0;
448 }
449 /* if our try counter reaches 0, bail out */
Michal Simekcfd8a6e2020-12-01 14:02:58 +0100450 debug(" %ld, data %d\n",
451 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000452 if (!maxtry--)
453 return result;
454 }
455 /* update to show what data was transferred */
456 this_xfer -= partial;
457 buf += partial;
458 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100459 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000460 }
461
462 /* if we get here, we're done and successful */
463 return 0;
464}
465
wdenkde887eb2003-09-10 18:20:28 +0000466static int usb_stor_BBB_reset(struct us_data *us)
467{
468 int result;
469 unsigned int pipe;
470
471 /*
472 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
473 *
474 * For Reset Recovery the host shall issue in the following order:
475 * a) a Bulk-Only Mass Storage Reset
476 * b) a Clear Feature HALT to the Bulk-In endpoint
477 * c) a Clear Feature HALT to the Bulk-Out endpoint
478 *
479 * This is done in 3 steps.
480 *
481 * If the reset doesn't succeed, the device should be port reset.
482 *
483 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
484 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530485 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100486 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
487 US_BBB_RESET,
488 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000489 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200490
Michael Trimarchi956a4352008-12-10 15:52:06 +0100491 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530492 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000493 return -1;
494 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200495
wdenkde887eb2003-09-10 18:20:28 +0000496 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000497 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530498 debug("BBB_reset result %d: status %lX reset\n",
499 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000500 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
501 result = usb_clear_halt(us->pusb_dev, pipe);
502 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000503 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530504 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
505 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000506 /* long wait for reset */
507 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
508 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000509 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530510 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
511 result, us->pusb_dev->status);
512 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000513 return 0;
514}
515
wdenkaffae2b2002-08-17 09:36:01 +0000516/* FIXME: this reset function doesn't really reset the port, and it
517 * should. Actually it should probably do what it's doing here, and
518 * reset the port physically
519 */
520static int usb_stor_CB_reset(struct us_data *us)
521{
522 unsigned char cmd[12];
523 int result;
524
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530525 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100526 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000527 cmd[0] = SCSI_SEND_DIAG;
528 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100529 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
530 US_CBI_ADSC,
531 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
532 0, us->ifnum, cmd, sizeof(cmd),
533 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000534
535 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000536 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530537 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
538 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000539 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
540 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
541
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530542 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000543 return 0;
544}
545
wdenkde887eb2003-09-10 18:20:28 +0000546/*
547 * Set up the command for a BBB device. Note that the actual SCSI
548 * command is copied into cbw.CBWCDB.
549 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600550static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000551{
552 int result;
553 int actlen;
554 int dir_in;
555 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600556 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000557
558 dir_in = US_DIRECTION(srb->cmd[0]);
559
560#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530561 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100562 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
563 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000564 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100565 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000566 printf("cmd[%d] %#x ", result, srb->cmd[result]);
567 printf("\n");
568 }
569#endif
570 /* sanity checks */
571 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530572 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000573 return -1;
574 }
575
576 /* always OUT to the ep */
577 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
578
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530579 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
580 cbw->dCBWTag = cpu_to_le32(CBWTag++);
581 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
582 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
583 cbw->bCBWLUN = srb->lun;
584 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000585 /* copy the command data into the CBW command data buffer */
586 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300587
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530588 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
589 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000591 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530592 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000593 return result;
594}
595
wdenkaffae2b2002-08-17 09:36:01 +0000596/* FIXME: we also need a CBI_command which sets up the completion
597 * interrupt, and waits for it
598 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600599static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000600{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200601 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100602 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000603 unsigned int pipe;
604 unsigned long status;
605
Michael Trimarchi956a4352008-12-10 15:52:06 +0100606 retry = 5;
607 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000608
Michael Trimarchi956a4352008-12-10 15:52:06 +0100609 if (dir_in)
610 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
611 else
612 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
613
614 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530615 debug("CBI gets a command: Try %d\n", 5 - retry);
616#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000617 usb_show_srb(srb);
618#endif
619 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100620 result = usb_control_msg(us->pusb_dev,
621 usb_sndctrlpipe(us->pusb_dev , 0),
622 US_CBI_ADSC,
623 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000624 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100625 srb->cmd, srb->cmdlen,
626 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530627 debug("CB_transport: control msg returned %d, status %lX\n",
628 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000629 /* check the return code for the command */
630 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100631 if (us->pusb_dev->status & USB_ST_STALLED) {
632 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530633 debug(" stall during command found," \
634 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100635 usb_clear_halt(us->pusb_dev,
636 usb_sndctrlpipe(us->pusb_dev, 0));
637 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000638 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530639 debug(" error during command %02X" \
640 " Stat = %lX\n", srb->cmd[0],
641 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000642 return result;
643 }
644 /* transfer the data payload for this command, if one exists*/
645
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530646 debug("CB_transport: control msg returned %d," \
647 " direction is %s to go 0x%lx\n", result,
648 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000649 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100650 result = us_one_transfer(us, pipe, (char *)srb->pdata,
651 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530652 debug("CBI attempted to transfer data," \
653 " result is %d status %lX, len %d\n",
654 result, us->pusb_dev->status,
655 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100656 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000657 break;
658 } /* if (srb->datalen) */
659 else
660 break;
661 }
662 /* return result */
663
664 return result;
665}
666
667
Simon Glass5fb559d2017-06-14 21:28:30 -0600668static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000669{
670 int timeout;
671
wdenk5f495752004-02-26 23:46:20 +0000672 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200673 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200674 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000675 timeout = 1000;
676 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300677 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000678 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000679 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000680 }
681 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100682 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000683 us->ip_wanted = 0;
684 return USB_STOR_TRANSPORT_ERROR;
685 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700686 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530687 us->ip_data, us->pusb_dev->irq_act_len,
688 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000689 /* UFI gives us ASC and ASCQ, like a request sense */
690 if (us->subclass == US_SC_UFI) {
691 if (srb->cmd[0] == SCSI_REQ_SENSE ||
692 srb->cmd[0] == SCSI_INQUIRY)
693 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000694 else if (us->ip_data)
695 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000696 else
wdenk5f495752004-02-26 23:46:20 +0000697 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000698 }
699 /* otherwise, we interpret the data normally */
700 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000701 case 0x0001:
702 return USB_STOR_TRANSPORT_GOOD;
703 case 0x0002:
704 return USB_STOR_TRANSPORT_FAILED;
705 default:
706 return USB_STOR_TRANSPORT_ERROR;
707 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000708 return USB_STOR_TRANSPORT_ERROR;
709}
710
711#define USB_TRANSPORT_UNKNOWN_RETRY 5
712#define USB_TRANSPORT_NOT_READY_RETRY 10
713
wdenkde887eb2003-09-10 18:20:28 +0000714/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000715static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000716{
wdenkde887eb2003-09-10 18:20:28 +0000717 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900718 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
719 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
720 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000721}
722
Simon Glass5fb559d2017-06-14 21:28:30 -0600723static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000724{
725 int result, retry;
726 int dir_in;
727 int actlen, data_actlen;
728 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600729 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000730#ifdef BBB_XPORT_TRACE
731 unsigned char *ptr;
732 int index;
733#endif
734
735 dir_in = US_DIRECTION(srb->cmd[0]);
736
737 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530738 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000739 result = usb_stor_BBB_comdat(srb, us);
740 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530741 debug("failed to send CBW status %ld\n",
742 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000743 usb_stor_BBB_reset(us);
744 return USB_STOR_TRANSPORT_FAILED;
745 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200746 if (!(us->flags & USB_READY))
747 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000748 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
749 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
750 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000751 data_actlen = 0;
752 /* no data, go immediately to the STATUS phase */
753 if (srb->datalen == 0)
754 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530755 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000756 if (dir_in)
757 pipe = pipein;
758 else
759 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300760
Michael Trimarchi956a4352008-12-10 15:52:06 +0100761 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
762 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000763 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100764 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530765 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000766 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100767 result = usb_stor_BBB_clear_endpt_stall(us,
768 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000769 if (result >= 0)
770 /* continue on to STATUS phase */
771 goto st;
772 }
773 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530774 debug("usb_bulk_msg error status %ld\n",
775 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000776 usb_stor_BBB_reset(us);
777 return USB_STOR_TRANSPORT_FAILED;
778 }
779#ifdef BBB_XPORT_TRACE
780 for (index = 0; index < data_actlen; index++)
781 printf("pdata[%d] %#x ", index, srb->pdata[index]);
782 printf("\n");
783#endif
784 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100785st:
wdenkde887eb2003-09-10 18:20:28 +0000786 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100787again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530788 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530789 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200790 &actlen, USB_CNTL_TIMEOUT*5);
791
wdenkde887eb2003-09-10 18:20:28 +0000792 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100793 if ((result < 0) && (retry < 1) &&
794 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530795 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000796 /* clear the STALL on the endpoint */
797 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
798 if (result >= 0 && (retry++ < 1))
799 /* do a retry */
800 goto again;
801 }
802 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530803 debug("usb_bulk_msg error status %ld\n",
804 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000805 usb_stor_BBB_reset(us);
806 return USB_STOR_TRANSPORT_FAILED;
807 }
808#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530809 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000810 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
811 printf("ptr[%d] %#x ", index, ptr[index]);
812 printf("\n");
813#endif
814 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530815 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000816 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
817 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530818 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530819 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000820 usb_stor_BBB_reset(us);
821 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530822 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530823 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000824 usb_stor_BBB_reset(us);
825 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530826 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530827 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000828 usb_stor_BBB_reset(us);
829 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530830 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530831 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000832 usb_stor_BBB_reset(us);
833 return USB_STOR_TRANSPORT_FAILED;
834 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530835 debug("transferred %dB instead of %ldB\n",
836 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000837 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530838 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530839 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000840 return USB_STOR_TRANSPORT_FAILED;
841 }
842
843 return result;
844}
845
Simon Glass5fb559d2017-06-14 21:28:30 -0600846static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000847{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600849 struct scsi_cmd *psrb;
850 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100851 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000852
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200853 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100854 status = USB_STOR_TRANSPORT_GOOD;
855 retry = 0;
856 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000857 /* issue the command */
858do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100859 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530860 debug("command / Data returned %d, status %lX\n",
861 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000862 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100863 if (us->protocol == US_PR_CBI) {
864 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000865 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100866 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530867 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000868 return status;
869 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
871 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
872 if (!us->ip_data) {
873 /* if the status is good, report it */
874 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530875 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000876 return status;
877 }
878 }
879 }
880 /* do we have to issue an auto request? */
881 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100882 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530883 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000884 us->transport_reset(us);
885 return USB_STOR_TRANSPORT_ERROR;
886 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100887 if ((us->protocol == US_PR_CBI) &&
888 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
889 (srb->cmd[0] == SCSI_INQUIRY))) {
890 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530891 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000892 return USB_STOR_TRANSPORT_GOOD;
893 }
894 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100895 memset(&psrb->cmd[0], 0, 12);
896 psrb->cmd[0] = SCSI_REQ_SENSE;
897 psrb->cmd[1] = srb->lun << 5;
898 psrb->cmd[4] = 18;
899 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200900 psrb->pdata = &srb->sense_buf[0];
Hector Martin7b3d10d2023-10-29 16:23:30 +0900901 psrb->cmdlen = us->cmd12 ? 12 : 6;
wdenkaffae2b2002-08-17 09:36:01 +0000902 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530904 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000905 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 if (us->protocol == US_PR_CBI)
907 status = usb_stor_CBI_get_status(psrb, us);
908
909 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530910 debug(" AUTO REQUEST ERROR %ld\n",
911 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000912 return USB_STOR_TRANSPORT_ERROR;
913 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530914 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
915 srb->sense_buf[0], srb->sense_buf[2],
916 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000917 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100918 if ((srb->sense_buf[2] == 0) &&
919 (srb->sense_buf[12] == 0) &&
920 (srb->sense_buf[13] == 0)) {
921 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000922 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100923 }
924
wdenkaffae2b2002-08-17 09:36:01 +0000925 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100926 switch (srb->sense_buf[2]) {
927 case 0x01:
928 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000929 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000930 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100931 case 0x02:
932 /* Not Ready */
933 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
934 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
935 " 0x%02X (NOT READY)\n", srb->cmd[0],
936 srb->sense_buf[0], srb->sense_buf[2],
937 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000938 return USB_STOR_TRANSPORT_FAILED;
939 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000940 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000941 goto do_retry;
942 }
943 break;
944 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100945 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
946 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
947 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
948 srb->sense_buf[2], srb->sense_buf[12],
949 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000950 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100951 } else
wdenkde887eb2003-09-10 18:20:28 +0000952 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000953 break;
wdenkaffae2b2002-08-17 09:36:01 +0000954 }
955 return USB_STOR_TRANSPORT_FAILED;
956}
957
Bin Meng9f447112017-09-07 06:13:21 -0700958static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
959 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700960{
Bin Mengf6e373e2017-09-07 06:13:20 -0700961 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200962 * Limit the total size of a transfer to 120 KB.
963 *
964 * Some devices are known to choke with anything larger. It seems like
965 * the problem stems from the fact that original IDE controllers had
966 * only an 8-bit register to hold the number of sectors in one transfer
967 * and even those couldn't handle a full 256 sectors.
968 *
969 * Because we want to make sure we interoperate with as many devices as
970 * possible, we will maintain a 240 sector transfer size limit for USB
971 * Mass Storage devices.
972 *
973 * Tests show that other operating have similar limits with Microsoft
974 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
975 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
976 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700977 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200978 unsigned short blk = 240;
979
980#if CONFIG_IS_ENABLED(DM_USB)
981 size_t size;
982 int ret;
983
Bin Meng9f447112017-09-07 06:13:21 -0700984 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200985 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700986 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700987#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700988
989 us->max_xfer_blk = blk;
990}
wdenkaffae2b2002-08-17 09:36:01 +0000991
Simon Glass5fb559d2017-06-14 21:28:30 -0600992static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000993{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100994 int retry, i;
995 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000996 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997 memset(&srb->cmd[0], 0, 12);
998 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200999 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001000 srb->cmd[4] = 36;
1001 srb->datalen = 36;
Hector Martin7b3d10d2023-10-29 16:23:30 +09001002 srb->cmdlen = ss->cmd12 ? 12 : 6;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001003 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301004 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001005 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +00001006 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +02001007 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +00001008
Michael Trimarchi956a4352008-12-10 15:52:06 +01001009 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +00001010 printf("error in inquiry\n");
1011 return -1;
1012 }
1013 return 0;
1014}
1015
Simon Glass5fb559d2017-06-14 21:28:30 -06001016static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001017{
1018 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001019
Michael Trimarchi956a4352008-12-10 15:52:06 +01001020 ptr = (char *)srb->pdata;
1021 memset(&srb->cmd[0], 0, 12);
1022 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001023 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001024 srb->cmd[4] = 18;
1025 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001026 srb->pdata = &srb->sense_buf[0];
Hector Martin7b3d10d2023-10-29 16:23:30 +09001027 srb->cmdlen = ss->cmd12 ? 12 : 6;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001028 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301029 debug("Request Sense returned %02X %02X %02X\n",
1030 srb->sense_buf[2], srb->sense_buf[12],
1031 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001032 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001033 return 0;
1034}
1035
Simon Glass5fb559d2017-06-14 21:28:30 -06001036static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001037{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001038 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001039
wdenkaffae2b2002-08-17 09:36:01 +00001040 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001041 memset(&srb->cmd[0], 0, 12);
1042 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001043 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001044 srb->datalen = 0;
Hector Martin7b3d10d2023-10-29 16:23:30 +09001045 srb->cmdlen = ss->cmd12 ? 12 : 6;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001046 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1047 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001048 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001049 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001050 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001051 /*
1052 * Check the Key Code Qualifier, if it matches
1053 * "Not Ready - medium not present"
1054 * (the sense Key equals 0x2 and the ASC is 0x3a)
1055 * return immediately as the medium being absent won't change
1056 * unless there is a user action.
1057 */
1058 if ((srb->sense_buf[2] == 0x02) &&
1059 (srb->sense_buf[12] == 0x3a))
1060 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001061 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001062 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001063
wdenkaffae2b2002-08-17 09:36:01 +00001064 return -1;
1065}
1066
Simon Glass5fb559d2017-06-14 21:28:30 -06001067static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001068{
1069 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001070 /* XXX retries */
1071 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001072 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001073 memset(&srb->cmd[0], 0, 12);
1074 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001075 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001076 srb->datalen = 8;
Hector Martin7b3d10d2023-10-29 16:23:30 +09001077 srb->cmdlen = ss->cmd12 ? 12 : 10;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001078 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001079 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001081
wdenkaffae2b2002-08-17 09:36:01 +00001082 return -1;
1083}
1084
Simon Glass5fb559d2017-06-14 21:28:30 -06001085static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1086 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001087{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001088 memset(&srb->cmd[0], 0, 12);
1089 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001090 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001091 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1092 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1093 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1094 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1095 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1096 srb->cmd[8] = (unsigned char) blocks & 0xff;
Hector Martin7b3d10d2023-10-29 16:23:30 +09001097 srb->cmdlen = ss->cmd12 ? 12 : 10;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301098 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001099 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001100}
1101
Simon Glass5fb559d2017-06-14 21:28:30 -06001102static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1103 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301104{
1105 memset(&srb->cmd[0], 0, 12);
1106 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001107 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301108 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1109 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1110 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1111 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1112 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1113 srb->cmd[8] = (unsigned char) blocks & 0xff;
Hector Martin7b3d10d2023-10-29 16:23:30 +09001114 srb->cmdlen = ss->cmd12 ? 12 : 10;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301115 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301116 return ss->transport(srb, ss);
1117}
1118
wdenkaffae2b2002-08-17 09:36:01 +00001119
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001120#ifdef CONFIG_USB_BIN_FIXUP
1121/*
1122 * Some USB storage devices queried for SCSI identification data respond with
1123 * binary strings, which if output to the console freeze the terminal. The
1124 * workaround is to modify the vendor and product strings read from such
1125 * device with proper values (as reported by 'usb info').
1126 *
1127 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001128 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001129 */
1130static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1131 unsigned char vendor[],
1132 unsigned char product[]) {
1133 const unsigned char max_vendor_len = 40;
1134 const unsigned char max_product_len = 20;
1135 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001136 strncpy((char *)vendor, "SMSC", max_vendor_len);
1137 strncpy((char *)product, "Flash Media Cntrller",
1138 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001139 }
1140}
1141#endif /* CONFIG_USB_BIN_FIXUP */
1142
Sven Schwermerc58ff202018-11-21 08:43:57 +01001143#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001144static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1145 lbaint_t blkcnt, void *buffer)
1146#else
Simon Glasse3394752016-02-29 15:25:34 -07001147static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001148 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001149#endif
wdenkaffae2b2002-08-17 09:36:01 +00001150{
Gabe Black7d077682012-10-12 14:26:07 +00001151 lbaint_t start, blks;
1152 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001153 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001154 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001155 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001156 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001157 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001158#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001159 struct blk_desc *block_dev;
1160#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001161
1162 if (blkcnt == 0)
1163 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001164 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001165#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001166 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001167 udev = dev_get_parent_priv(dev_get_parent(dev));
1168 debug("\nusb_read: udev %d\n", block_dev->devnum);
1169#else
Simon Glass99e598e2016-02-29 15:25:54 -07001170 debug("\nusb_read: udev %d\n", block_dev->devnum);
1171 udev = usb_dev_desc[block_dev->devnum].priv;
1172 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001173 debug("%s: No device\n", __func__);
1174 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001175 }
Simon Glass01f5be92016-02-29 15:25:58 -07001176#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001177 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001178
1179 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001180 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001181 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001182 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001183 start = blknr;
1184 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001185
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001186 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1187 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001188
wdenkaffae2b2002-08-17 09:36:01 +00001189 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001190 /* XXX need some comment here */
1191 retry = 2;
1192 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001193 if (blks > ss->max_xfer_blk)
1194 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001195 else
1196 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001197retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001198 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001199 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001200 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001201 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001202 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301203 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001204 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001205 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001206 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001207 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001208 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001209 break;
1210 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001211 start += smallblks;
1212 blks -= smallblks;
1213 buf_addr += srb->datalen;
1214 } while (blks != 0);
1215
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001216 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301217 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001218
Marek Vasut118a9032020-04-06 14:29:44 +02001219 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001220 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001221 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001222 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001223 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001224}
1225
Sven Schwermerc58ff202018-11-21 08:43:57 +01001226#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001227static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1228 lbaint_t blkcnt, const void *buffer)
1229#else
Simon Glasse3394752016-02-29 15:25:34 -07001230static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001231 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001232#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301233{
Gabe Black7d077682012-10-12 14:26:07 +00001234 lbaint_t start, blks;
1235 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301236 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001237 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001238 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001239 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001240 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001241#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001242 struct blk_desc *block_dev;
1243#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301244
1245 if (blkcnt == 0)
1246 return 0;
1247
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301248 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001249#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001250 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001251 udev = dev_get_parent_priv(dev_get_parent(dev));
1252 debug("\nusb_read: udev %d\n", block_dev->devnum);
1253#else
Simon Glass99e598e2016-02-29 15:25:54 -07001254 debug("\nusb_read: udev %d\n", block_dev->devnum);
1255 udev = usb_dev_desc[block_dev->devnum].priv;
1256 if (!udev) {
1257 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001258 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001259 }
Simon Glass01f5be92016-02-29 15:25:58 -07001260#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001261 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301262
1263 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001264 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301265
Simon Glass99e598e2016-02-29 15:25:54 -07001266 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001267 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301268 start = blknr;
1269 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301270
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001271 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1272 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301273
1274 do {
1275 /* If write fails retry for max retry count else
1276 * return with number of blocks written successfully.
1277 */
1278 retry = 2;
1279 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001280 if (blks > ss->max_xfer_blk)
1281 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301282 else
1283 smallblks = (unsigned short) blks;
1284retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001285 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301286 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001287 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301288 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001289 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301290 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001291 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001292 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301293 if (retry--)
1294 goto retry_it;
1295 blkcnt -= blks;
1296 break;
1297 }
1298 start += smallblks;
1299 blks -= smallblks;
1300 buf_addr += srb->datalen;
1301 } while (blks != 0);
1302
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001303 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1304 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301305
Marek Vasut118a9032020-04-06 14:29:44 +02001306 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301307 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001308 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001309 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301310 return blkcnt;
1311
1312}
wdenkaffae2b2002-08-17 09:36:01 +00001313
1314/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001315int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1316 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001317{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001318 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001319 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301320 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001321 unsigned int flags = 0;
1322
wdenkaffae2b2002-08-17 09:36:01 +00001323 /* let's examine the device now */
1324 iface = &dev->config.if_desc[ifnum];
1325
wdenkaffae2b2002-08-17 09:36:01 +00001326 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001327 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1328 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1329 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001330 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001331 /* if it's not a mass storage, we go no further */
1332 return 0;
1333 }
1334
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001335 memset(ss, 0, sizeof(struct us_data));
1336
wdenkaffae2b2002-08-17 09:36:01 +00001337 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301338 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001339
1340 /* Initialize the us_data structure with some useful info */
1341 ss->flags = flags;
1342 ss->ifnum = ifnum;
1343 ss->pusb_dev = dev;
1344 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001345 ss->subclass = iface->desc.bInterfaceSubClass;
1346 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001347
1348 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301349 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001350 switch (ss->protocol) {
1351 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301352 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001353 ss->transport = usb_stor_CB_transport;
1354 ss->transport_reset = usb_stor_CB_reset;
1355 break;
1356
1357 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301358 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001359 ss->transport = usb_stor_CB_transport;
1360 ss->transport_reset = usb_stor_CB_reset;
1361 break;
wdenkde887eb2003-09-10 18:20:28 +00001362 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301363 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001364 ss->transport = usb_stor_BBB_transport;
1365 ss->transport_reset = usb_stor_BBB_reset;
1366 break;
wdenkaffae2b2002-08-17 09:36:01 +00001367 default:
wdenk5f495752004-02-26 23:46:20 +00001368 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001369 return 0;
1370 break;
1371 }
1372
1373 /*
1374 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1375 * An optional interrupt is OK (necessary for CBI protocol).
1376 * We will ignore any others.
1377 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001378 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301379 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001380 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301381 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001382 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301383 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1384 ss->ep_in = ep_desc->bEndpointAddress &
1385 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001386 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001387 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301388 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001389 USB_ENDPOINT_NUMBER_MASK;
1390 }
1391
1392 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301393 if ((ep_desc->bmAttributes &
1394 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1395 ss->ep_int = ep_desc->bEndpointAddress &
1396 USB_ENDPOINT_NUMBER_MASK;
1397 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001398 }
1399 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301400 debug("Endpoints In %d Out %d Int %d\n",
1401 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001402
1403 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001404 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001405 !ss->ep_in || !ss->ep_out ||
1406 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301407 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001408 return 0;
1409 }
1410 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001411 /* We only handle certain protocols. Currently, these are
1412 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001413 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001414 */
wdenk5f495752004-02-26 23:46:20 +00001415 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1416 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001417 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001418 return 0;
1419 }
Hector Martin7b3d10d2023-10-29 16:23:30 +09001420
1421 /* UFI uses 12-byte commands (like RBC, unlike SCSI) */
1422 if (ss->subclass == US_SC_UFI)
1423 ss->cmd12 = true;
1424
Michael Trimarchi956a4352008-12-10 15:52:06 +01001425 if (ss->ep_int) {
1426 /* we had found an interrupt endpoint, prepare irq pipe
1427 * set up the IRQ pipe and handler
1428 */
wdenkaffae2b2002-08-17 09:36:01 +00001429 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1430 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1431 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001432 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001433 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001434
1435 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001436 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001437
Michael Trimarchi956a4352008-12-10 15:52:06 +01001438 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001439 return 1;
1440}
1441
Michael Trimarchi956a4352008-12-10 15:52:06 +01001442int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001443 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001444{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001445 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001446 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1447 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1448 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001449 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001450
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001451 pccb->pdata = usb_stor_buf;
1452
1453 dev_desc->target = dev->devnum;
1454 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301455 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001456
Simon Glass78330d62015-03-25 12:22:12 -06001457 if (usb_inquiry(pccb, ss)) {
1458 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001459 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001460 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001461
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001462 perq = usb_stor_buf[0];
1463 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001464
Soeren Moche4828002014-11-08 07:02:14 +01001465 /*
1466 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1467 * they would not respond to test_unit_ready .
1468 */
1469 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001470 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001471 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001472 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001473 if ((modi&0x80) == 0x80) {
1474 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001475 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001476 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001477 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1478 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1479 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001480 dev_desc->vendor[8] = 0;
1481 dev_desc->product[16] = 0;
1482 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001483#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001484 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1485 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001486#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301487 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1488 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001489 if (usb_test_unit_ready(pccb, ss)) {
1490 printf("Device NOT ready\n"
1491 " Request Sense returned %02X %02X %02X\n",
1492 pccb->sense_buf[2], pccb->sense_buf[12],
1493 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001494 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001495 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001496 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001497 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001498 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001499 memset(pccb->pdata, 0, 8);
1500 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001501 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001502 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001503 cap[0] = 2880;
1504 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001505 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001506 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001507#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001508 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1509 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001510
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001511 cap[0] = cpu_to_be32(cap[0]);
1512 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001513#endif
1514
1515 capacity = be32_to_cpu(cap[0]) + 1;
1516 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001517
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001518 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1519 dev_desc->lba = capacity;
1520 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001521 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001522 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301523 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001524
wdenkaffae2b2002-08-17 09:36:01 +00001525 return 1;
1526}
Simon Glassac9774e2015-03-25 12:22:16 -06001527
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001528#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001529
1530static int usb_mass_storage_probe(struct udevice *dev)
1531{
Simon Glassde44acf2015-09-28 23:32:01 -06001532 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001533 int ret;
1534
1535 usb_disable_asynch(1); /* asynch transfer not allowed */
1536 ret = usb_stor_probe_device(udev);
1537 usb_disable_asynch(0); /* asynch transfer allowed */
1538
1539 return ret;
1540}
1541
1542static const struct udevice_id usb_mass_storage_ids[] = {
1543 { .compatible = "usb-mass-storage" },
1544 { }
1545};
1546
1547U_BOOT_DRIVER(usb_mass_storage) = {
1548 .name = "usb_mass_storage",
1549 .id = UCLASS_MASS_STORAGE,
1550 .of_match = usb_mass_storage_ids,
1551 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001552#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001553 .plat_auto = sizeof(struct us_data),
Simon Glass01f5be92016-02-29 15:25:58 -07001554#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001555};
1556
1557UCLASS_DRIVER(usb_mass_storage) = {
1558 .id = UCLASS_MASS_STORAGE,
1559 .name = "usb_mass_storage",
1560};
1561
1562static const struct usb_device_id mass_storage_id_table[] = {
1563 {
1564 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1565 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1566 },
1567 { } /* Terminating entry */
1568};
1569
Simon Glass46952fb2015-07-06 16:47:51 -06001570U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001571#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001572
Sven Schwermerc58ff202018-11-21 08:43:57 +01001573#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001574static const struct blk_ops usb_storage_ops = {
1575 .read = usb_stor_read,
1576 .write = usb_stor_write,
1577};
1578
1579U_BOOT_DRIVER(usb_storage_blk) = {
1580 .name = "usb_storage_blk",
1581 .id = UCLASS_BLK,
1582 .ops = &usb_storage_ops,
1583};
Simon Glassd3171412016-05-01 11:36:06 -06001584#else
1585U_BOOT_LEGACY_BLK(usb) = {
Simon Glassfada3f92022-09-17 09:00:09 -06001586 .uclass_idname = "usb",
1587 .uclass_id = UCLASS_USB,
Simon Glassd3171412016-05-01 11:36:06 -06001588 .max_devs = USB_MAX_STOR_DEV,
1589 .desc = usb_dev_desc,
1590};
Simon Glassac9774e2015-03-25 12:22:16 -06001591#endif