blob: e59c819bac582377f30a61f4d172f96c36598a65 [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>
Simon Glasse1917ef2022-04-24 23:31:23 -060037#include <bootdev.h>
wdenkaffae2b2002-08-17 09:36:01 +000038#include <command.h>
Simon Glassac9774e2015-03-25 12:22:16 -060039#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060040#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060041#include <log.h>
Simon Glass332a9b62015-03-25 12:22:14 -060042#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060043#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020044#include <asm/byteorder.h>
Simon Glass274e0b02020-05-10 11:39:56 -060045#include <asm/cache.h>
wdenkaffae2b2002-08-17 09:36:01 +000046#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060047#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070048#include <dm/lists.h>
Simon Glassdbd79542020-05-10 11:40:11 -060049#include <linux/delay.h>
wdenkaffae2b2002-08-17 09:36:01 +000050
Grant Likelyffc2dd72007-02-20 09:04:34 +010051#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000052#include <usb.h>
53
wdenk5f495752004-02-26 23:46:20 +000054#undef BBB_COMDAT_TRACE
55#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000056
wdenkaffae2b2002-08-17 09:36:01 +000057#include <scsi.h>
58/* direction table -- this indicates the direction of the data
59 * transfer for each command code -- a 1 indicates input
60 */
Mike Frysinger165522b2010-10-20 07:16:04 -040061static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000062 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
63 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
66};
67#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
68
Simon Glass5fb559d2017-06-14 21:28:30 -060069static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010070static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000071
Michael Trimarchi956a4352008-12-10 15:52:06 +010072static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000073
Sven Schwermerc58ff202018-11-21 08:43:57 +010074#if !CONFIG_IS_ENABLED(BLK)
Simon Glasse3394752016-02-29 15:25:34 -070075static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070076#endif
wdenkaffae2b2002-08-17 09:36:01 +000077
78struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060079typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010080typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000081
82struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010083 struct usb_device *pusb_dev; /* this usb_device */
84
85 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020086# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010087 unsigned char ifnum; /* interface number */
88 unsigned char ep_in; /* in endpoint */
89 unsigned char ep_out; /* out ....... */
90 unsigned char ep_int; /* interrupt . */
91 unsigned char subclass; /* as in overview */
92 unsigned char protocol; /* .............. */
93 unsigned char attention_done; /* force attn on first cmd */
94 unsigned short ip_data; /* interrupt data */
95 int action; /* what to do */
96 int ip_wanted; /* needed */
97 int *irq_handle; /* for USB int requests */
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020098 unsigned int irqpipe; /* pipe for release_irq */
Michael Trimarchi956a4352008-12-10 15:52:06 +010099 unsigned char irqmaxp; /* max packed for irq Pipe */
100 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -0600101 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100102 trans_reset transport_reset; /* reset routine */
103 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -0700104 unsigned short max_xfer_blk; /* maximum transfer blocks */
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,
Simon Glassdbfa32c2022-08-11 19:34:59 -0600222 UCLASS_USB, usb_max_devs, 512, 0,
Simon Glass966b6952016-05-01 11:36:29 -0600223 &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;
242 }
AKASHI Takahirof9c3cc82022-03-08 20:36:40 +0900243
244 ret = blk_probe_or_unbind(dev);
245 if (ret)
246 return ret;
Simon Glasse1917ef2022-04-24 23:31:23 -0600247
248 ret = bootdev_setup_sibling_blk(dev, "usb_bootdev");
249 if (ret) {
250 int ret2;
251
252 ret2 = device_unbind(dev);
253 if (ret2)
254 return log_msg_ret("bootdev", ret2);
255 return log_msg_ret("bootdev", ret);
256 }
Simon Glass01f5be92016-02-29 15:25:58 -0700257 }
258#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700259 /* We don't have space to even probe if we hit the maximum */
260 if (usb_max_devs == USB_MAX_STOR_DEV) {
261 printf("max USB Storage Device reached: %d stopping\n",
262 usb_max_devs);
263 return -ENOSPC;
264 }
265
Simon Glass99e598e2016-02-29 15:25:54 -0700266 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
267 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600268
Simon Glass99e598e2016-02-29 15:25:54 -0700269 /*
270 * OK, it's a storage device. Iterate over its LUNs and populate
271 * usb_dev_desc'
272 */
273 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600274
Simon Glass99e598e2016-02-29 15:25:54 -0700275 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
276 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
277 lun++) {
278 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600279
Simon Glass99e598e2016-02-29 15:25:54 -0700280 blkdev = &usb_dev_desc[usb_max_devs];
281 memset(blkdev, '\0', sizeof(struct blk_desc));
Simon Glassfada3f92022-09-17 09:00:09 -0600282 blkdev->uclass_id = UCLASS_USB;
Simon Glass99e598e2016-02-29 15:25:54 -0700283 blkdev->devnum = usb_max_devs;
284 blkdev->part_type = PART_TYPE_UNKNOWN;
285 blkdev->target = 0xff;
286 blkdev->type = DEV_TYPE_UNKNOWN;
287 blkdev->block_read = usb_stor_read;
288 blkdev->block_write = usb_stor_write;
289 blkdev->lun = lun;
290 blkdev->priv = udev;
291
292 if (usb_stor_get_info(udev, &usb_stor[start],
293 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700294 debug("partype: %d\n", blkdev->part_type);
295 part_init(blkdev);
296 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700297 usb_max_devs++;
298 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600299 }
300 }
Simon Glass01f5be92016-02-29 15:25:58 -0700301#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600302
Simon Glassdf7d34f2015-03-25 12:22:15 -0600303 return 0;
304}
305
306void usb_stor_reset(void)
307{
308 usb_max_devs = 0;
309}
310
Michael Trimarchi956a4352008-12-10 15:52:06 +0100311/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200312 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000313 * to the user if mode = 1
314 * returns current device or -1 if no
315 */
316int usb_stor_scan(int mode)
317{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100318 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200319 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100320
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100321#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100322 unsigned char i;
323
wdenkaffae2b2002-08-17 09:36:01 +0000324 usb_disable_asynch(1); /* asynch transfer not allowed */
325
Simon Glassdf7d34f2015-03-25 12:22:15 -0600326 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100327 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600328 struct usb_device *dev;
329
Michael Trimarchi956a4352008-12-10 15:52:06 +0100330 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530331 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600332 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000333 break;
wdenkaffae2b2002-08-17 09:36:01 +0000334 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200335
wdenkaffae2b2002-08-17 09:36:01 +0000336 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100337#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200338 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100339 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000340 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100341 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000342}
343
344static int usb_stor_irq(struct usb_device *dev)
345{
346 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100347 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000348
Michael Trimarchi956a4352008-12-10 15:52:06 +0100349 if (us->ip_wanted)
350 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000351 return 0;
352}
353
354
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530355#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000356
Simon Glass5fb559d2017-06-14 21:28:30 -0600357static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000358{
359 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100360 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
361 for (i = 0; i < 12; i++)
362 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000363 printf("\n");
364}
365
366static void display_int_status(unsigned long tmp)
367{
368 printf("Status: %s %s %s %s %s %s %s\n",
369 (tmp & USB_ST_ACTIVE) ? "Active" : "",
370 (tmp & USB_ST_STALLED) ? "Stalled" : "",
371 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
372 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
373 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
374 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
375 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
376}
377#endif
378/***********************************************************************
379 * Data transfer routines
380 ***********************************************************************/
381
382static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
383{
384 int max_size;
385 int this_xfer;
386 int result;
387 int partial;
388 int maxtry;
389 int stat;
390
391 /* determine the maximum packet size for these transfers */
392 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
393
394 /* while we have data left to transfer */
395 while (length) {
396
397 /* calculate how long this will be -- maximum or a remainder */
398 this_xfer = length > max_size ? max_size : length;
399 length -= this_xfer;
400
401 /* setup the retry counter */
402 maxtry = 10;
403
404 /* set up the transfer loop */
405 do {
406 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600407 debug("Bulk xfer 0x%lx(%d) try #%d\n",
408 (ulong)map_to_sysmem(buf), this_xfer,
409 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000410 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100411 this_xfer, &partial,
412 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530413 debug("bulk_msg returned %d xferred %d/%d\n",
414 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100415 if (us->pusb_dev->status != 0) {
416 /* if we stall, we need to clear it before
417 * we go on
418 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530419#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000420 display_int_status(us->pusb_dev->status);
421#endif
422 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530423 debug("stalled ->clearing endpoint" \
424 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000425 stat = us->pusb_dev->status;
426 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100427 us->pusb_dev->status = stat;
428 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530429 debug("bulk transferred" \
430 "with error %lX," \
431 " but data ok\n",
432 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000433 return 0;
434 }
435 else
436 return result;
437 }
438 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530439 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000440 return result;
441 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530442 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100443 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530444 debug(" %ld, but data ok\n",
445 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000446 return 0;
447 }
448 /* if our try counter reaches 0, bail out */
Michal Simekcfd8a6e2020-12-01 14:02:58 +0100449 debug(" %ld, data %d\n",
450 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000451 if (!maxtry--)
452 return result;
453 }
454 /* update to show what data was transferred */
455 this_xfer -= partial;
456 buf += partial;
457 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100458 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000459 }
460
461 /* if we get here, we're done and successful */
462 return 0;
463}
464
wdenkde887eb2003-09-10 18:20:28 +0000465static int usb_stor_BBB_reset(struct us_data *us)
466{
467 int result;
468 unsigned int pipe;
469
470 /*
471 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
472 *
473 * For Reset Recovery the host shall issue in the following order:
474 * a) a Bulk-Only Mass Storage Reset
475 * b) a Clear Feature HALT to the Bulk-In endpoint
476 * c) a Clear Feature HALT to the Bulk-Out endpoint
477 *
478 * This is done in 3 steps.
479 *
480 * If the reset doesn't succeed, the device should be port reset.
481 *
482 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
483 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530484 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100485 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
486 US_BBB_RESET,
487 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000488 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200489
Michael Trimarchi956a4352008-12-10 15:52:06 +0100490 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530491 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000492 return -1;
493 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200494
wdenkde887eb2003-09-10 18:20:28 +0000495 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000496 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530497 debug("BBB_reset result %d: status %lX reset\n",
498 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000499 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
500 result = usb_clear_halt(us->pusb_dev, pipe);
501 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000502 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530503 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
504 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000505 /* long wait for reset */
506 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
507 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000508 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530509 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
510 result, us->pusb_dev->status);
511 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000512 return 0;
513}
514
wdenkaffae2b2002-08-17 09:36:01 +0000515/* FIXME: this reset function doesn't really reset the port, and it
516 * should. Actually it should probably do what it's doing here, and
517 * reset the port physically
518 */
519static int usb_stor_CB_reset(struct us_data *us)
520{
521 unsigned char cmd[12];
522 int result;
523
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530524 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100525 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000526 cmd[0] = SCSI_SEND_DIAG;
527 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100528 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
529 US_CBI_ADSC,
530 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
531 0, us->ifnum, cmd, sizeof(cmd),
532 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000533
534 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000535 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530536 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
537 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000538 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
539 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
540
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530541 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000542 return 0;
543}
544
wdenkde887eb2003-09-10 18:20:28 +0000545/*
546 * Set up the command for a BBB device. Note that the actual SCSI
547 * command is copied into cbw.CBWCDB.
548 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600549static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000550{
551 int result;
552 int actlen;
553 int dir_in;
554 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600555 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000556
557 dir_in = US_DIRECTION(srb->cmd[0]);
558
559#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530560 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100561 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
562 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000563 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100564 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000565 printf("cmd[%d] %#x ", result, srb->cmd[result]);
566 printf("\n");
567 }
568#endif
569 /* sanity checks */
570 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530571 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000572 return -1;
573 }
574
575 /* always OUT to the ep */
576 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
577
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530578 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
579 cbw->dCBWTag = cpu_to_le32(CBWTag++);
580 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
581 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
582 cbw->bCBWLUN = srb->lun;
583 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000584 /* copy the command data into the CBW command data buffer */
585 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300586
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530587 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
588 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100589 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000590 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530591 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000592 return result;
593}
594
wdenkaffae2b2002-08-17 09:36:01 +0000595/* FIXME: we also need a CBI_command which sets up the completion
596 * interrupt, and waits for it
597 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600598static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000599{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200600 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100601 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000602 unsigned int pipe;
603 unsigned long status;
604
Michael Trimarchi956a4352008-12-10 15:52:06 +0100605 retry = 5;
606 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000607
Michael Trimarchi956a4352008-12-10 15:52:06 +0100608 if (dir_in)
609 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
610 else
611 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
612
613 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530614 debug("CBI gets a command: Try %d\n", 5 - retry);
615#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000616 usb_show_srb(srb);
617#endif
618 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100619 result = usb_control_msg(us->pusb_dev,
620 usb_sndctrlpipe(us->pusb_dev , 0),
621 US_CBI_ADSC,
622 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000623 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100624 srb->cmd, srb->cmdlen,
625 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530626 debug("CB_transport: control msg returned %d, status %lX\n",
627 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000628 /* check the return code for the command */
629 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100630 if (us->pusb_dev->status & USB_ST_STALLED) {
631 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530632 debug(" stall during command found," \
633 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100634 usb_clear_halt(us->pusb_dev,
635 usb_sndctrlpipe(us->pusb_dev, 0));
636 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000637 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530638 debug(" error during command %02X" \
639 " Stat = %lX\n", srb->cmd[0],
640 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000641 return result;
642 }
643 /* transfer the data payload for this command, if one exists*/
644
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530645 debug("CB_transport: control msg returned %d," \
646 " direction is %s to go 0x%lx\n", result,
647 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000648 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100649 result = us_one_transfer(us, pipe, (char *)srb->pdata,
650 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530651 debug("CBI attempted to transfer data," \
652 " result is %d status %lX, len %d\n",
653 result, us->pusb_dev->status,
654 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100655 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000656 break;
657 } /* if (srb->datalen) */
658 else
659 break;
660 }
661 /* return result */
662
663 return result;
664}
665
666
Simon Glass5fb559d2017-06-14 21:28:30 -0600667static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000668{
669 int timeout;
670
wdenk5f495752004-02-26 23:46:20 +0000671 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200672 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200673 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000674 timeout = 1000;
675 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300676 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000677 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000678 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000679 }
680 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100681 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000682 us->ip_wanted = 0;
683 return USB_STOR_TRANSPORT_ERROR;
684 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700685 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530686 us->ip_data, us->pusb_dev->irq_act_len,
687 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000688 /* UFI gives us ASC and ASCQ, like a request sense */
689 if (us->subclass == US_SC_UFI) {
690 if (srb->cmd[0] == SCSI_REQ_SENSE ||
691 srb->cmd[0] == SCSI_INQUIRY)
692 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000693 else if (us->ip_data)
694 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000695 else
wdenk5f495752004-02-26 23:46:20 +0000696 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000697 }
698 /* otherwise, we interpret the data normally */
699 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000700 case 0x0001:
701 return USB_STOR_TRANSPORT_GOOD;
702 case 0x0002:
703 return USB_STOR_TRANSPORT_FAILED;
704 default:
705 return USB_STOR_TRANSPORT_ERROR;
706 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000707 return USB_STOR_TRANSPORT_ERROR;
708}
709
710#define USB_TRANSPORT_UNKNOWN_RETRY 5
711#define USB_TRANSPORT_NOT_READY_RETRY 10
712
wdenkde887eb2003-09-10 18:20:28 +0000713/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000714static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000715{
wdenkde887eb2003-09-10 18:20:28 +0000716 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900717 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
718 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
719 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000720}
721
Simon Glass5fb559d2017-06-14 21:28:30 -0600722static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000723{
724 int result, retry;
725 int dir_in;
726 int actlen, data_actlen;
727 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600728 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000729#ifdef BBB_XPORT_TRACE
730 unsigned char *ptr;
731 int index;
732#endif
733
734 dir_in = US_DIRECTION(srb->cmd[0]);
735
736 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530737 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000738 result = usb_stor_BBB_comdat(srb, us);
739 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530740 debug("failed to send CBW status %ld\n",
741 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000742 usb_stor_BBB_reset(us);
743 return USB_STOR_TRANSPORT_FAILED;
744 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200745 if (!(us->flags & USB_READY))
746 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000747 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
748 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
749 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000750 data_actlen = 0;
751 /* no data, go immediately to the STATUS phase */
752 if (srb->datalen == 0)
753 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530754 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000755 if (dir_in)
756 pipe = pipein;
757 else
758 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300759
Michael Trimarchi956a4352008-12-10 15:52:06 +0100760 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
761 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000762 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100763 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530764 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000765 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100766 result = usb_stor_BBB_clear_endpt_stall(us,
767 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000768 if (result >= 0)
769 /* continue on to STATUS phase */
770 goto st;
771 }
772 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530773 debug("usb_bulk_msg error status %ld\n",
774 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000775 usb_stor_BBB_reset(us);
776 return USB_STOR_TRANSPORT_FAILED;
777 }
778#ifdef BBB_XPORT_TRACE
779 for (index = 0; index < data_actlen; index++)
780 printf("pdata[%d] %#x ", index, srb->pdata[index]);
781 printf("\n");
782#endif
783 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100784st:
wdenkde887eb2003-09-10 18:20:28 +0000785 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100786again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530787 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530788 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200789 &actlen, USB_CNTL_TIMEOUT*5);
790
wdenkde887eb2003-09-10 18:20:28 +0000791 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100792 if ((result < 0) && (retry < 1) &&
793 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530794 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000795 /* clear the STALL on the endpoint */
796 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
797 if (result >= 0 && (retry++ < 1))
798 /* do a retry */
799 goto again;
800 }
801 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530802 debug("usb_bulk_msg error status %ld\n",
803 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000804 usb_stor_BBB_reset(us);
805 return USB_STOR_TRANSPORT_FAILED;
806 }
807#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530808 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000809 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
810 printf("ptr[%d] %#x ", index, ptr[index]);
811 printf("\n");
812#endif
813 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530814 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000815 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
816 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530817 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530818 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000819 usb_stor_BBB_reset(us);
820 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530821 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530822 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000823 usb_stor_BBB_reset(us);
824 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530825 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530826 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000827 usb_stor_BBB_reset(us);
828 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530829 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530830 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000831 usb_stor_BBB_reset(us);
832 return USB_STOR_TRANSPORT_FAILED;
833 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530834 debug("transferred %dB instead of %ldB\n",
835 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000836 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530837 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530838 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000839 return USB_STOR_TRANSPORT_FAILED;
840 }
841
842 return result;
843}
844
Simon Glass5fb559d2017-06-14 21:28:30 -0600845static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000846{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600848 struct scsi_cmd *psrb;
849 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100850 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000851
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200852 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100853 status = USB_STOR_TRANSPORT_GOOD;
854 retry = 0;
855 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000856 /* issue the command */
857do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100858 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530859 debug("command / Data returned %d, status %lX\n",
860 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000861 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100862 if (us->protocol == US_PR_CBI) {
863 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000864 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100865 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530866 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000867 return status;
868 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100869 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
870 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
871 if (!us->ip_data) {
872 /* if the status is good, report it */
873 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530874 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000875 return status;
876 }
877 }
878 }
879 /* do we have to issue an auto request? */
880 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530882 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000883 us->transport_reset(us);
884 return USB_STOR_TRANSPORT_ERROR;
885 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100886 if ((us->protocol == US_PR_CBI) &&
887 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
888 (srb->cmd[0] == SCSI_INQUIRY))) {
889 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530890 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000891 return USB_STOR_TRANSPORT_GOOD;
892 }
893 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100894 memset(&psrb->cmd[0], 0, 12);
895 psrb->cmd[0] = SCSI_REQ_SENSE;
896 psrb->cmd[1] = srb->lun << 5;
897 psrb->cmd[4] = 18;
898 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200899 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100900 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000901 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100902 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530903 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000904 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100905 if (us->protocol == US_PR_CBI)
906 status = usb_stor_CBI_get_status(psrb, us);
907
908 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530909 debug(" AUTO REQUEST ERROR %ld\n",
910 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000911 return USB_STOR_TRANSPORT_ERROR;
912 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530913 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
914 srb->sense_buf[0], srb->sense_buf[2],
915 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000916 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100917 if ((srb->sense_buf[2] == 0) &&
918 (srb->sense_buf[12] == 0) &&
919 (srb->sense_buf[13] == 0)) {
920 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000921 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100922 }
923
wdenkaffae2b2002-08-17 09:36:01 +0000924 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100925 switch (srb->sense_buf[2]) {
926 case 0x01:
927 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000928 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000929 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100930 case 0x02:
931 /* Not Ready */
932 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
933 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
934 " 0x%02X (NOT READY)\n", srb->cmd[0],
935 srb->sense_buf[0], srb->sense_buf[2],
936 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000937 return USB_STOR_TRANSPORT_FAILED;
938 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000939 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000940 goto do_retry;
941 }
942 break;
943 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100944 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
945 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
946 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
947 srb->sense_buf[2], srb->sense_buf[12],
948 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000949 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100950 } else
wdenkde887eb2003-09-10 18:20:28 +0000951 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000952 break;
wdenkaffae2b2002-08-17 09:36:01 +0000953 }
954 return USB_STOR_TRANSPORT_FAILED;
955}
956
Bin Meng9f447112017-09-07 06:13:21 -0700957static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
958 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700959{
Bin Mengf6e373e2017-09-07 06:13:20 -0700960 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200961 * Limit the total size of a transfer to 120 KB.
962 *
963 * Some devices are known to choke with anything larger. It seems like
964 * the problem stems from the fact that original IDE controllers had
965 * only an 8-bit register to hold the number of sectors in one transfer
966 * and even those couldn't handle a full 256 sectors.
967 *
968 * Because we want to make sure we interoperate with as many devices as
969 * possible, we will maintain a 240 sector transfer size limit for USB
970 * Mass Storage devices.
971 *
972 * Tests show that other operating have similar limits with Microsoft
973 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
974 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
975 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700976 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200977 unsigned short blk = 240;
978
979#if CONFIG_IS_ENABLED(DM_USB)
980 size_t size;
981 int ret;
982
Bin Meng9f447112017-09-07 06:13:21 -0700983 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200984 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700985 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700986#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700987
988 us->max_xfer_blk = blk;
989}
wdenkaffae2b2002-08-17 09:36:01 +0000990
Simon Glass5fb559d2017-06-14 21:28:30 -0600991static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000992{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100993 int retry, i;
994 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000995 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100996 memset(&srb->cmd[0], 0, 12);
997 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200998 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100999 srb->cmd[4] = 36;
1000 srb->datalen = 36;
1001 srb->cmdlen = 12;
1002 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301003 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001004 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +00001005 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +02001006 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +00001007
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +00001009 printf("error in inquiry\n");
1010 return -1;
1011 }
1012 return 0;
1013}
1014
Simon Glass5fb559d2017-06-14 21:28:30 -06001015static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001016{
1017 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001018
Michael Trimarchi956a4352008-12-10 15:52:06 +01001019 ptr = (char *)srb->pdata;
1020 memset(&srb->cmd[0], 0, 12);
1021 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001022 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001023 srb->cmd[4] = 18;
1024 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001025 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001026 srb->cmdlen = 12;
1027 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301028 debug("Request Sense returned %02X %02X %02X\n",
1029 srb->sense_buf[2], srb->sense_buf[12],
1030 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001032 return 0;
1033}
1034
Simon Glass5fb559d2017-06-14 21:28:30 -06001035static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001036{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001037 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001038
wdenkaffae2b2002-08-17 09:36:01 +00001039 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001040 memset(&srb->cmd[0], 0, 12);
1041 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001042 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001043 srb->datalen = 0;
1044 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001045 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1046 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001047 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001048 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001050 /*
1051 * Check the Key Code Qualifier, if it matches
1052 * "Not Ready - medium not present"
1053 * (the sense Key equals 0x2 and the ASC is 0x3a)
1054 * return immediately as the medium being absent won't change
1055 * unless there is a user action.
1056 */
1057 if ((srb->sense_buf[2] == 0x02) &&
1058 (srb->sense_buf[12] == 0x3a))
1059 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001060 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001061 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001062
wdenkaffae2b2002-08-17 09:36:01 +00001063 return -1;
1064}
1065
Simon Glass5fb559d2017-06-14 21:28:30 -06001066static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001067{
1068 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 /* XXX retries */
1070 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001071 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072 memset(&srb->cmd[0], 0, 12);
1073 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001074 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001075 srb->datalen = 8;
1076 srb->cmdlen = 12;
1077 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001078 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001079 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001080
wdenkaffae2b2002-08-17 09:36:01 +00001081 return -1;
1082}
1083
Simon Glass5fb559d2017-06-14 21:28:30 -06001084static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1085 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001086{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001087 memset(&srb->cmd[0], 0, 12);
1088 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001089 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001090 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1091 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1092 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1093 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1094 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1095 srb->cmd[8] = (unsigned char) blocks & 0xff;
1096 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301097 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001098 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001099}
1100
Simon Glass5fb559d2017-06-14 21:28:30 -06001101static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1102 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301103{
1104 memset(&srb->cmd[0], 0, 12);
1105 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001106 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301107 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1108 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1109 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1110 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1111 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1112 srb->cmd[8] = (unsigned char) blocks & 0xff;
1113 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301114 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301115 return ss->transport(srb, ss);
1116}
1117
wdenkaffae2b2002-08-17 09:36:01 +00001118
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001119#ifdef CONFIG_USB_BIN_FIXUP
1120/*
1121 * Some USB storage devices queried for SCSI identification data respond with
1122 * binary strings, which if output to the console freeze the terminal. The
1123 * workaround is to modify the vendor and product strings read from such
1124 * device with proper values (as reported by 'usb info').
1125 *
1126 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001127 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001128 */
1129static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1130 unsigned char vendor[],
1131 unsigned char product[]) {
1132 const unsigned char max_vendor_len = 40;
1133 const unsigned char max_product_len = 20;
1134 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001135 strncpy((char *)vendor, "SMSC", max_vendor_len);
1136 strncpy((char *)product, "Flash Media Cntrller",
1137 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001138 }
1139}
1140#endif /* CONFIG_USB_BIN_FIXUP */
1141
Sven Schwermerc58ff202018-11-21 08:43:57 +01001142#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001143static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1144 lbaint_t blkcnt, void *buffer)
1145#else
Simon Glasse3394752016-02-29 15:25:34 -07001146static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001147 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001148#endif
wdenkaffae2b2002-08-17 09:36:01 +00001149{
Gabe Black7d077682012-10-12 14:26:07 +00001150 lbaint_t start, blks;
1151 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001152 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001153 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001154 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001155 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001156 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001157#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001158 struct blk_desc *block_dev;
1159#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001160
1161 if (blkcnt == 0)
1162 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001163 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001164#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001165 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001166 udev = dev_get_parent_priv(dev_get_parent(dev));
1167 debug("\nusb_read: udev %d\n", block_dev->devnum);
1168#else
Simon Glass99e598e2016-02-29 15:25:54 -07001169 debug("\nusb_read: udev %d\n", block_dev->devnum);
1170 udev = usb_dev_desc[block_dev->devnum].priv;
1171 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001172 debug("%s: No device\n", __func__);
1173 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001174 }
Simon Glass01f5be92016-02-29 15:25:58 -07001175#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001176 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001177
1178 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001179 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001180 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001181 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001182 start = blknr;
1183 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001184
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001185 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1186 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001187
wdenkaffae2b2002-08-17 09:36:01 +00001188 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001189 /* XXX need some comment here */
1190 retry = 2;
1191 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001192 if (blks > ss->max_xfer_blk)
1193 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001194 else
1195 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001196retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001197 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001198 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001199 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001200 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001201 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301202 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001203 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001204 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001205 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001206 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001207 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001208 break;
1209 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001210 start += smallblks;
1211 blks -= smallblks;
1212 buf_addr += srb->datalen;
1213 } while (blks != 0);
1214
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001215 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301216 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001217
Marek Vasut118a9032020-04-06 14:29:44 +02001218 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001219 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001220 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001221 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001222 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001223}
1224
Sven Schwermerc58ff202018-11-21 08:43:57 +01001225#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001226static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1227 lbaint_t blkcnt, const void *buffer)
1228#else
Simon Glasse3394752016-02-29 15:25:34 -07001229static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001230 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001231#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301232{
Gabe Black7d077682012-10-12 14:26:07 +00001233 lbaint_t start, blks;
1234 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301235 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001236 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001237 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001238 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001239 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001240#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001241 struct blk_desc *block_dev;
1242#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301243
1244 if (blkcnt == 0)
1245 return 0;
1246
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301247 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001248#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001249 block_dev = dev_get_uclass_plat(dev);
Simon Glass01f5be92016-02-29 15:25:58 -07001250 udev = dev_get_parent_priv(dev_get_parent(dev));
1251 debug("\nusb_read: udev %d\n", block_dev->devnum);
1252#else
Simon Glass99e598e2016-02-29 15:25:54 -07001253 debug("\nusb_read: udev %d\n", block_dev->devnum);
1254 udev = usb_dev_desc[block_dev->devnum].priv;
1255 if (!udev) {
1256 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001257 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001258 }
Simon Glass01f5be92016-02-29 15:25:58 -07001259#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001260 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301261
1262 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001263 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301264
Simon Glass99e598e2016-02-29 15:25:54 -07001265 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001266 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301267 start = blknr;
1268 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301269
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001270 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1271 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301272
1273 do {
1274 /* If write fails retry for max retry count else
1275 * return with number of blocks written successfully.
1276 */
1277 retry = 2;
1278 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001279 if (blks > ss->max_xfer_blk)
1280 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301281 else
1282 smallblks = (unsigned short) blks;
1283retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001284 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301285 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001286 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301287 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001288 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301289 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001290 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001291 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301292 if (retry--)
1293 goto retry_it;
1294 blkcnt -= blks;
1295 break;
1296 }
1297 start += smallblks;
1298 blks -= smallblks;
1299 buf_addr += srb->datalen;
1300 } while (blks != 0);
1301
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001302 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1303 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301304
Marek Vasut118a9032020-04-06 14:29:44 +02001305 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301306 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001307 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001308 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301309 return blkcnt;
1310
1311}
wdenkaffae2b2002-08-17 09:36:01 +00001312
1313/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001314int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1315 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001316{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001317 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001318 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301319 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001320 unsigned int flags = 0;
1321
wdenkaffae2b2002-08-17 09:36:01 +00001322 /* let's examine the device now */
1323 iface = &dev->config.if_desc[ifnum];
1324
wdenkaffae2b2002-08-17 09:36:01 +00001325 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001326 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1327 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1328 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001329 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001330 /* if it's not a mass storage, we go no further */
1331 return 0;
1332 }
1333
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001334 memset(ss, 0, sizeof(struct us_data));
1335
wdenkaffae2b2002-08-17 09:36:01 +00001336 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301337 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001338
1339 /* Initialize the us_data structure with some useful info */
1340 ss->flags = flags;
1341 ss->ifnum = ifnum;
1342 ss->pusb_dev = dev;
1343 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001344 ss->subclass = iface->desc.bInterfaceSubClass;
1345 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001346
1347 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301348 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001349 switch (ss->protocol) {
1350 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301351 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001352 ss->transport = usb_stor_CB_transport;
1353 ss->transport_reset = usb_stor_CB_reset;
1354 break;
1355
1356 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301357 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001358 ss->transport = usb_stor_CB_transport;
1359 ss->transport_reset = usb_stor_CB_reset;
1360 break;
wdenkde887eb2003-09-10 18:20:28 +00001361 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301362 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001363 ss->transport = usb_stor_BBB_transport;
1364 ss->transport_reset = usb_stor_BBB_reset;
1365 break;
wdenkaffae2b2002-08-17 09:36:01 +00001366 default:
wdenk5f495752004-02-26 23:46:20 +00001367 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001368 return 0;
1369 break;
1370 }
1371
1372 /*
1373 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1374 * An optional interrupt is OK (necessary for CBI protocol).
1375 * We will ignore any others.
1376 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001377 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301378 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001379 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301380 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001381 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301382 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1383 ss->ep_in = ep_desc->bEndpointAddress &
1384 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001385 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001386 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301387 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001388 USB_ENDPOINT_NUMBER_MASK;
1389 }
1390
1391 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301392 if ((ep_desc->bmAttributes &
1393 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1394 ss->ep_int = ep_desc->bEndpointAddress &
1395 USB_ENDPOINT_NUMBER_MASK;
1396 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001397 }
1398 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301399 debug("Endpoints In %d Out %d Int %d\n",
1400 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001401
1402 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001403 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001404 !ss->ep_in || !ss->ep_out ||
1405 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301406 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001407 return 0;
1408 }
1409 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001410 /* We only handle certain protocols. Currently, these are
1411 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001412 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001413 */
wdenk5f495752004-02-26 23:46:20 +00001414 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1415 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001416 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001417 return 0;
1418 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001419 if (ss->ep_int) {
1420 /* we had found an interrupt endpoint, prepare irq pipe
1421 * set up the IRQ pipe and handler
1422 */
wdenkaffae2b2002-08-17 09:36:01 +00001423 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1424 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1425 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001426 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001427 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001428
1429 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001430 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001431
Michael Trimarchi956a4352008-12-10 15:52:06 +01001432 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001433 return 1;
1434}
1435
Michael Trimarchi956a4352008-12-10 15:52:06 +01001436int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001437 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001438{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001439 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001440 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1441 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1442 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001443 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001444
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001445 pccb->pdata = usb_stor_buf;
1446
1447 dev_desc->target = dev->devnum;
1448 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301449 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001450
Simon Glass78330d62015-03-25 12:22:12 -06001451 if (usb_inquiry(pccb, ss)) {
1452 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001453 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001454 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001455
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001456 perq = usb_stor_buf[0];
1457 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001458
Soeren Moche4828002014-11-08 07:02:14 +01001459 /*
1460 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1461 * they would not respond to test_unit_ready .
1462 */
1463 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001464 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001465 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001466 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001467 if ((modi&0x80) == 0x80) {
1468 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001469 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001470 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001471 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1472 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1473 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001474 dev_desc->vendor[8] = 0;
1475 dev_desc->product[16] = 0;
1476 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001477#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001478 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1479 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001480#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301481 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1482 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001483 if (usb_test_unit_ready(pccb, ss)) {
1484 printf("Device NOT ready\n"
1485 " Request Sense returned %02X %02X %02X\n",
1486 pccb->sense_buf[2], pccb->sense_buf[12],
1487 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001488 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001489 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001490 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001491 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001492 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001493 memset(pccb->pdata, 0, 8);
1494 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001495 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001496 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001497 cap[0] = 2880;
1498 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001499 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001500 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001501#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001502 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1503 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001504
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001505 cap[0] = cpu_to_be32(cap[0]);
1506 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001507#endif
1508
1509 capacity = be32_to_cpu(cap[0]) + 1;
1510 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001511
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001512 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1513 dev_desc->lba = capacity;
1514 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001515 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001516 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301517 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001518
wdenkaffae2b2002-08-17 09:36:01 +00001519 return 1;
1520}
Simon Glassac9774e2015-03-25 12:22:16 -06001521
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001522#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001523
1524static int usb_mass_storage_probe(struct udevice *dev)
1525{
Simon Glassde44acf2015-09-28 23:32:01 -06001526 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001527 int ret;
1528
1529 usb_disable_asynch(1); /* asynch transfer not allowed */
1530 ret = usb_stor_probe_device(udev);
1531 usb_disable_asynch(0); /* asynch transfer allowed */
1532
1533 return ret;
1534}
1535
1536static const struct udevice_id usb_mass_storage_ids[] = {
1537 { .compatible = "usb-mass-storage" },
1538 { }
1539};
1540
1541U_BOOT_DRIVER(usb_mass_storage) = {
1542 .name = "usb_mass_storage",
1543 .id = UCLASS_MASS_STORAGE,
1544 .of_match = usb_mass_storage_ids,
1545 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001546#if CONFIG_IS_ENABLED(BLK)
Simon Glass71fa5b42020-12-03 16:55:18 -07001547 .plat_auto = sizeof(struct us_data),
Simon Glass01f5be92016-02-29 15:25:58 -07001548#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001549};
1550
1551UCLASS_DRIVER(usb_mass_storage) = {
1552 .id = UCLASS_MASS_STORAGE,
1553 .name = "usb_mass_storage",
1554};
1555
1556static const struct usb_device_id mass_storage_id_table[] = {
1557 {
1558 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1559 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1560 },
1561 { } /* Terminating entry */
1562};
1563
Simon Glass46952fb2015-07-06 16:47:51 -06001564U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001565#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001566
Sven Schwermerc58ff202018-11-21 08:43:57 +01001567#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001568static const struct blk_ops usb_storage_ops = {
1569 .read = usb_stor_read,
1570 .write = usb_stor_write,
1571};
1572
1573U_BOOT_DRIVER(usb_storage_blk) = {
1574 .name = "usb_storage_blk",
1575 .id = UCLASS_BLK,
1576 .ops = &usb_storage_ops,
1577};
Simon Glassd3171412016-05-01 11:36:06 -06001578#else
1579U_BOOT_LEGACY_BLK(usb) = {
Simon Glassfada3f92022-09-17 09:00:09 -06001580 .uclass_idname = "usb",
1581 .uclass_id = UCLASS_USB,
Simon Glassd3171412016-05-01 11:36:06 -06001582 .max_devs = USB_MAX_STOR_DEV,
1583 .desc = usb_dev_desc,
1584};
Simon Glassac9774e2015-03-25 12:22:16 -06001585#endif