blob: 743a239084607e21b9e298e032f629cd6c7f8e42 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00002/*
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +02003 * Most of this source has been derived from the Linux USB
4 * project:
5 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
6 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
7 * (c) 1999 Michael Gee (michael@linuxspecific.com)
8 * (c) 2000 Yggdrasil Computing, Inc.
9 *
10 *
11 * Adapted for U-Boot:
12 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
Simon Glassac9774e2015-03-25 12:22:16 -060013 * Driver model conversion:
14 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000015 *
wdenkde887eb2003-09-10 18:20:28 +000016 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020017 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000018 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020019 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000020 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000021 */
22
23/* Note:
24 * Currently only the CBI transport protocoll has been implemented, and it
25 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
26 * transport protocoll may work as well.
27 */
wdenkde887eb2003-09-10 18:20:28 +000028/*
29 * New Note:
30 * Support for USB Mass Storage Devices (BBB) has been added. It has
31 * only been tested with USB memory sticks.
wdenkde887eb2003-09-10 18:20:28 +000032 */
wdenkaffae2b2002-08-17 09:36:01 +000033
34
wdenkaffae2b2002-08-17 09:36:01 +000035#include <common.h>
Simon Glass655306c2020-05-10 11:39:58 -060036#include <blk.h>
wdenkaffae2b2002-08-17 09:36:01 +000037#include <command.h>
Simon Glassac9774e2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060040#include <log.h>
Simon Glass332a9b62015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020043#include <asm/byteorder.h>
Simon Glass274e0b02020-05-10 11:39:56 -060044#include <asm/cache.h>
wdenkaffae2b2002-08-17 09:36:01 +000045#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060046#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070047#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000048
Grant Likelyffc2dd72007-02-20 09:04:34 +010049#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000050#include <usb.h>
51
wdenk5f495752004-02-26 23:46:20 +000052#undef BBB_COMDAT_TRACE
53#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000054
wdenkaffae2b2002-08-17 09:36:01 +000055#include <scsi.h>
56/* direction table -- this indicates the direction of the data
57 * transfer for each command code -- a 1 indicates input
58 */
Mike Frysinger165522b2010-10-20 07:16:04 -040059static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000060 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
61 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
64};
65#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
66
Simon Glass5fb559d2017-06-14 21:28:30 -060067static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010068static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000069
Michael Trimarchi956a4352008-12-10 15:52:06 +010070static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000071
Sven Schwermerc58ff202018-11-21 08:43:57 +010072#if !CONFIG_IS_ENABLED(BLK)
Simon Glasse3394752016-02-29 15:25:34 -070073static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070074#endif
wdenkaffae2b2002-08-17 09:36:01 +000075
76struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060077typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010078typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000079
80struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010081 struct usb_device *pusb_dev; /* this usb_device */
82
83 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020084# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010085 unsigned char ifnum; /* interface number */
86 unsigned char ep_in; /* in endpoint */
87 unsigned char ep_out; /* out ....... */
88 unsigned char ep_int; /* interrupt . */
89 unsigned char subclass; /* as in overview */
90 unsigned char protocol; /* .............. */
91 unsigned char attention_done; /* force attn on first cmd */
92 unsigned short ip_data; /* interrupt data */
93 int action; /* what to do */
94 int ip_wanted; /* needed */
95 int *irq_handle; /* for USB int requests */
96 unsigned int irqpipe; /* pipe for release_irq */
97 unsigned char irqmaxp; /* max packed for irq Pipe */
98 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -060099 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100100 trans_reset transport_reset; /* reset routine */
101 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -0700102 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000103};
104
Sven Schwermerc58ff202018-11-21 08:43:57 +0100105#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000106static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700107#endif
wdenkaffae2b2002-08-17 09:36:01 +0000108
wdenk5f495752004-02-26 23:46:20 +0000109#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000110#define USB_STOR_TRANSPORT_FAILED -1
111#define USB_STOR_TRANSPORT_ERROR -2
112
Michael Trimarchi956a4352008-12-10 15:52:06 +0100113int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700114 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100115int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
116 struct us_data *ss);
Sven Schwermerc58ff202018-11-21 08:43:57 +0100117#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700118static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
119 lbaint_t blkcnt, void *buffer);
120static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
121 lbaint_t blkcnt, const void *buffer);
122#else
Simon Glasse3394752016-02-29 15:25:34 -0700123static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700124 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700125static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700126 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700127#endif
wdenkaffae2b2002-08-17 09:36:01 +0000128void uhci_show_temp_int_td(void);
129
Kim Phillipsb052b602012-10-29 13:34:32 +0000130static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000131{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200132 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000133}
134
Michael Trimarchi956a4352008-12-10 15:52:06 +0100135/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200136 * show info on storage devices; 'usb start/init' must be invoked earlier
137 * as we only retrieve structures populated during devices initialization
138 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100139int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200140{
Simon Glass99e598e2016-02-29 15:25:54 -0700141 int count = 0;
Sven Schwermerc58ff202018-11-21 08:43:57 +0100142#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700143 struct udevice *dev;
144
145 for (blk_first_device(IF_TYPE_USB, &dev);
146 dev;
147 blk_next_device(&dev)) {
148 struct blk_desc *desc = dev_get_uclass_platdata(dev);
149
150 printf(" Device %d: ", desc->devnum);
151 dev_print(desc);
152 count++;
153 }
154#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200155 int i;
156
Aras Vaichas7ede1862008-03-25 12:09:07 +1100157 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200158 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100159 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200160 dev_print(&usb_dev_desc[i]);
161 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100162 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100163 }
Simon Glass01f5be92016-02-29 15:25:58 -0700164#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700165 if (!count) {
166 printf("No storage devices, perhaps not 'usb start'ed..?\n");
167 return 1;
168 }
169
Simon Glass8c6c0742016-03-16 07:45:44 -0600170 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200171}
172
Ludovic Courtès134396c2010-10-05 22:04:26 +0200173static unsigned int usb_get_max_lun(struct us_data *us)
174{
175 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530176 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200177 len = usb_control_msg(us->pusb_dev,
178 usb_rcvctrlpipe(us->pusb_dev, 0),
179 US_BBB_GET_MAX_LUN,
180 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
181 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530182 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200183 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530184 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530185 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200186}
187
Simon Glass99e598e2016-02-29 15:25:54 -0700188static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600189{
Simon Glass99e598e2016-02-29 15:25:54 -0700190 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700191
Sven Schwermerc58ff202018-11-21 08:43:57 +0100192#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700193 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700194 int ret;
195#else
Simon Glass99e598e2016-02-29 15:25:54 -0700196 int start;
197
198 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600199 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700200#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600201
Simon Glass01f5be92016-02-29 15:25:58 -0700202 debug("\n\nProbing for storage\n");
Sven Schwermerc58ff202018-11-21 08:43:57 +0100203#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700204 /*
205 * We store the us_data in the mass storage device's platdata. It
206 * is shared by all LUNs (block devices) attached to this mass storage
207 * device.
208 */
209 data = dev_get_platdata(udev->dev);
210 if (!usb_storage_probe(udev, 0, data))
211 return 0;
212 max_lun = usb_get_max_lun(data);
213 for (lun = 0; lun <= max_lun; lun++) {
214 struct blk_desc *blkdev;
215 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600216 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700217
Simon Glass966b6952016-05-01 11:36:29 -0600218 snprintf(str, sizeof(str), "lun%d", lun);
219 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
220 IF_TYPE_USB, usb_max_devs, 512, 0,
221 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700222 if (ret) {
223 debug("Cannot bind driver\n");
224 return ret;
225 }
226
227 blkdev = dev_get_uclass_platdata(dev);
228 blkdev->target = 0xff;
229 blkdev->lun = lun;
230
231 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengcbc3da82018-10-15 02:21:07 -0700232 if (ret == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700233 usb_max_devs++;
234 debug("%s: Found device %p\n", __func__, udev);
235 } else {
236 debug("usb_stor_get_info: Invalid device\n");
237 ret = device_unbind(dev);
238 if (ret)
239 return ret;
240 }
241 }
242#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700243 /* We don't have space to even probe if we hit the maximum */
244 if (usb_max_devs == USB_MAX_STOR_DEV) {
245 printf("max USB Storage Device reached: %d stopping\n",
246 usb_max_devs);
247 return -ENOSPC;
248 }
249
Simon Glass99e598e2016-02-29 15:25:54 -0700250 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
251 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600252
Simon Glass99e598e2016-02-29 15:25:54 -0700253 /*
254 * OK, it's a storage device. Iterate over its LUNs and populate
255 * usb_dev_desc'
256 */
257 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600258
Simon Glass99e598e2016-02-29 15:25:54 -0700259 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
260 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
261 lun++) {
262 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600263
Simon Glass99e598e2016-02-29 15:25:54 -0700264 blkdev = &usb_dev_desc[usb_max_devs];
265 memset(blkdev, '\0', sizeof(struct blk_desc));
266 blkdev->if_type = IF_TYPE_USB;
267 blkdev->devnum = usb_max_devs;
268 blkdev->part_type = PART_TYPE_UNKNOWN;
269 blkdev->target = 0xff;
270 blkdev->type = DEV_TYPE_UNKNOWN;
271 blkdev->block_read = usb_stor_read;
272 blkdev->block_write = usb_stor_write;
273 blkdev->lun = lun;
274 blkdev->priv = udev;
275
276 if (usb_stor_get_info(udev, &usb_stor[start],
277 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700278 debug("partype: %d\n", blkdev->part_type);
279 part_init(blkdev);
280 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700281 usb_max_devs++;
282 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600283 }
284 }
Simon Glass01f5be92016-02-29 15:25:58 -0700285#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600286
Simon Glassdf7d34f2015-03-25 12:22:15 -0600287 return 0;
288}
289
290void usb_stor_reset(void)
291{
292 usb_max_devs = 0;
293}
294
Michael Trimarchi956a4352008-12-10 15:52:06 +0100295/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200296 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000297 * to the user if mode = 1
298 * returns current device or -1 if no
299 */
300int usb_stor_scan(int mode)
301{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100302 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200303 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100304
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100305#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100306 unsigned char i;
307
wdenkaffae2b2002-08-17 09:36:01 +0000308 usb_disable_asynch(1); /* asynch transfer not allowed */
309
Simon Glassdf7d34f2015-03-25 12:22:15 -0600310 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100311 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600312 struct usb_device *dev;
313
Michael Trimarchi956a4352008-12-10 15:52:06 +0100314 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530315 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600316 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000317 break;
wdenkaffae2b2002-08-17 09:36:01 +0000318 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200319
wdenkaffae2b2002-08-17 09:36:01 +0000320 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100321#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200322 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100323 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000324 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100325 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000326}
327
328static int usb_stor_irq(struct usb_device *dev)
329{
330 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100331 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000332
Michael Trimarchi956a4352008-12-10 15:52:06 +0100333 if (us->ip_wanted)
334 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000335 return 0;
336}
337
338
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530339#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000340
Simon Glass5fb559d2017-06-14 21:28:30 -0600341static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000342{
343 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100344 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
345 for (i = 0; i < 12; i++)
346 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000347 printf("\n");
348}
349
350static void display_int_status(unsigned long tmp)
351{
352 printf("Status: %s %s %s %s %s %s %s\n",
353 (tmp & USB_ST_ACTIVE) ? "Active" : "",
354 (tmp & USB_ST_STALLED) ? "Stalled" : "",
355 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
356 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
357 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
358 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
359 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
360}
361#endif
362/***********************************************************************
363 * Data transfer routines
364 ***********************************************************************/
365
366static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
367{
368 int max_size;
369 int this_xfer;
370 int result;
371 int partial;
372 int maxtry;
373 int stat;
374
375 /* determine the maximum packet size for these transfers */
376 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
377
378 /* while we have data left to transfer */
379 while (length) {
380
381 /* calculate how long this will be -- maximum or a remainder */
382 this_xfer = length > max_size ? max_size : length;
383 length -= this_xfer;
384
385 /* setup the retry counter */
386 maxtry = 10;
387
388 /* set up the transfer loop */
389 do {
390 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600391 debug("Bulk xfer 0x%lx(%d) try #%d\n",
392 (ulong)map_to_sysmem(buf), this_xfer,
393 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000394 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100395 this_xfer, &partial,
396 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530397 debug("bulk_msg returned %d xferred %d/%d\n",
398 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100399 if (us->pusb_dev->status != 0) {
400 /* if we stall, we need to clear it before
401 * we go on
402 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530403#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000404 display_int_status(us->pusb_dev->status);
405#endif
406 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530407 debug("stalled ->clearing endpoint" \
408 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000409 stat = us->pusb_dev->status;
410 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100411 us->pusb_dev->status = stat;
412 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530413 debug("bulk transferred" \
414 "with error %lX," \
415 " but data ok\n",
416 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000417 return 0;
418 }
419 else
420 return result;
421 }
422 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530423 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000424 return result;
425 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530426 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100427 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530428 debug(" %ld, but data ok\n",
429 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000430 return 0;
431 }
432 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530433 debug(" %ld, data %d\n",
434 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000435 if (!maxtry--)
436 return result;
437 }
438 /* update to show what data was transferred */
439 this_xfer -= partial;
440 buf += partial;
441 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100442 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000443 }
444
445 /* if we get here, we're done and successful */
446 return 0;
447}
448
wdenkde887eb2003-09-10 18:20:28 +0000449static int usb_stor_BBB_reset(struct us_data *us)
450{
451 int result;
452 unsigned int pipe;
453
454 /*
455 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
456 *
457 * For Reset Recovery the host shall issue in the following order:
458 * a) a Bulk-Only Mass Storage Reset
459 * b) a Clear Feature HALT to the Bulk-In endpoint
460 * c) a Clear Feature HALT to the Bulk-Out endpoint
461 *
462 * This is done in 3 steps.
463 *
464 * If the reset doesn't succeed, the device should be port reset.
465 *
466 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
467 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530468 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100469 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
470 US_BBB_RESET,
471 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000472 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200473
Michael Trimarchi956a4352008-12-10 15:52:06 +0100474 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530475 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000476 return -1;
477 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200478
wdenkde887eb2003-09-10 18:20:28 +0000479 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000480 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530481 debug("BBB_reset result %d: status %lX reset\n",
482 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000483 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
484 result = usb_clear_halt(us->pusb_dev, pipe);
485 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000486 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530487 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
488 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000489 /* long wait for reset */
490 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
491 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000492 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530493 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
494 result, us->pusb_dev->status);
495 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000496 return 0;
497}
498
wdenkaffae2b2002-08-17 09:36:01 +0000499/* FIXME: this reset function doesn't really reset the port, and it
500 * should. Actually it should probably do what it's doing here, and
501 * reset the port physically
502 */
503static int usb_stor_CB_reset(struct us_data *us)
504{
505 unsigned char cmd[12];
506 int result;
507
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530508 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100509 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000510 cmd[0] = SCSI_SEND_DIAG;
511 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100512 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
513 US_CBI_ADSC,
514 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
515 0, us->ifnum, cmd, sizeof(cmd),
516 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000517
518 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000519 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530520 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
521 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000522 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
523 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
524
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530525 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000526 return 0;
527}
528
wdenkde887eb2003-09-10 18:20:28 +0000529/*
530 * Set up the command for a BBB device. Note that the actual SCSI
531 * command is copied into cbw.CBWCDB.
532 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600533static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000534{
535 int result;
536 int actlen;
537 int dir_in;
538 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600539 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000540
541 dir_in = US_DIRECTION(srb->cmd[0]);
542
543#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530544 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100545 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
546 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000547 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100548 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000549 printf("cmd[%d] %#x ", result, srb->cmd[result]);
550 printf("\n");
551 }
552#endif
553 /* sanity checks */
554 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530555 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000556 return -1;
557 }
558
559 /* always OUT to the ep */
560 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
561
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530562 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
563 cbw->dCBWTag = cpu_to_le32(CBWTag++);
564 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
565 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
566 cbw->bCBWLUN = srb->lun;
567 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000568 /* copy the command data into the CBW command data buffer */
569 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300570
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530571 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
572 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100573 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000574 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530575 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000576 return result;
577}
578
wdenkaffae2b2002-08-17 09:36:01 +0000579/* FIXME: we also need a CBI_command which sets up the completion
580 * interrupt, and waits for it
581 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600582static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000583{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200584 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100585 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000586 unsigned int pipe;
587 unsigned long status;
588
Michael Trimarchi956a4352008-12-10 15:52:06 +0100589 retry = 5;
590 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000591
Michael Trimarchi956a4352008-12-10 15:52:06 +0100592 if (dir_in)
593 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
594 else
595 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
596
597 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530598 debug("CBI gets a command: Try %d\n", 5 - retry);
599#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000600 usb_show_srb(srb);
601#endif
602 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100603 result = usb_control_msg(us->pusb_dev,
604 usb_sndctrlpipe(us->pusb_dev , 0),
605 US_CBI_ADSC,
606 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000607 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100608 srb->cmd, srb->cmdlen,
609 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530610 debug("CB_transport: control msg returned %d, status %lX\n",
611 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000612 /* check the return code for the command */
613 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100614 if (us->pusb_dev->status & USB_ST_STALLED) {
615 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530616 debug(" stall during command found," \
617 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100618 usb_clear_halt(us->pusb_dev,
619 usb_sndctrlpipe(us->pusb_dev, 0));
620 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000621 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530622 debug(" error during command %02X" \
623 " Stat = %lX\n", srb->cmd[0],
624 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000625 return result;
626 }
627 /* transfer the data payload for this command, if one exists*/
628
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530629 debug("CB_transport: control msg returned %d," \
630 " direction is %s to go 0x%lx\n", result,
631 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000632 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100633 result = us_one_transfer(us, pipe, (char *)srb->pdata,
634 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530635 debug("CBI attempted to transfer data," \
636 " result is %d status %lX, len %d\n",
637 result, us->pusb_dev->status,
638 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100639 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000640 break;
641 } /* if (srb->datalen) */
642 else
643 break;
644 }
645 /* return result */
646
647 return result;
648}
649
650
Simon Glass5fb559d2017-06-14 21:28:30 -0600651static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000652{
653 int timeout;
654
wdenk5f495752004-02-26 23:46:20 +0000655 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200656 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200657 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000658 timeout = 1000;
659 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300660 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000661 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000662 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000663 }
664 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100665 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000666 us->ip_wanted = 0;
667 return USB_STOR_TRANSPORT_ERROR;
668 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700669 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530670 us->ip_data, us->pusb_dev->irq_act_len,
671 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000672 /* UFI gives us ASC and ASCQ, like a request sense */
673 if (us->subclass == US_SC_UFI) {
674 if (srb->cmd[0] == SCSI_REQ_SENSE ||
675 srb->cmd[0] == SCSI_INQUIRY)
676 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000677 else if (us->ip_data)
678 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000679 else
wdenk5f495752004-02-26 23:46:20 +0000680 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000681 }
682 /* otherwise, we interpret the data normally */
683 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000684 case 0x0001:
685 return USB_STOR_TRANSPORT_GOOD;
686 case 0x0002:
687 return USB_STOR_TRANSPORT_FAILED;
688 default:
689 return USB_STOR_TRANSPORT_ERROR;
690 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000691 return USB_STOR_TRANSPORT_ERROR;
692}
693
694#define USB_TRANSPORT_UNKNOWN_RETRY 5
695#define USB_TRANSPORT_NOT_READY_RETRY 10
696
wdenkde887eb2003-09-10 18:20:28 +0000697/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000698static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000699{
wdenkde887eb2003-09-10 18:20:28 +0000700 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900701 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
702 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
703 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000704}
705
Simon Glass5fb559d2017-06-14 21:28:30 -0600706static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000707{
708 int result, retry;
709 int dir_in;
710 int actlen, data_actlen;
711 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600712 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000713#ifdef BBB_XPORT_TRACE
714 unsigned char *ptr;
715 int index;
716#endif
717
718 dir_in = US_DIRECTION(srb->cmd[0]);
719
720 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530721 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000722 result = usb_stor_BBB_comdat(srb, us);
723 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530724 debug("failed to send CBW status %ld\n",
725 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000726 usb_stor_BBB_reset(us);
727 return USB_STOR_TRANSPORT_FAILED;
728 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200729 if (!(us->flags & USB_READY))
730 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000731 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
732 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
733 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000734 data_actlen = 0;
735 /* no data, go immediately to the STATUS phase */
736 if (srb->datalen == 0)
737 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530738 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000739 if (dir_in)
740 pipe = pipein;
741 else
742 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300743
Michael Trimarchi956a4352008-12-10 15:52:06 +0100744 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
745 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000746 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100747 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530748 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000749 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100750 result = usb_stor_BBB_clear_endpt_stall(us,
751 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000752 if (result >= 0)
753 /* continue on to STATUS phase */
754 goto st;
755 }
756 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530757 debug("usb_bulk_msg error status %ld\n",
758 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000759 usb_stor_BBB_reset(us);
760 return USB_STOR_TRANSPORT_FAILED;
761 }
762#ifdef BBB_XPORT_TRACE
763 for (index = 0; index < data_actlen; index++)
764 printf("pdata[%d] %#x ", index, srb->pdata[index]);
765 printf("\n");
766#endif
767 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100768st:
wdenkde887eb2003-09-10 18:20:28 +0000769 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100770again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530771 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530772 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200773 &actlen, USB_CNTL_TIMEOUT*5);
774
wdenkde887eb2003-09-10 18:20:28 +0000775 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100776 if ((result < 0) && (retry < 1) &&
777 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530778 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000779 /* clear the STALL on the endpoint */
780 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
781 if (result >= 0 && (retry++ < 1))
782 /* do a retry */
783 goto again;
784 }
785 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530786 debug("usb_bulk_msg error status %ld\n",
787 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000788 usb_stor_BBB_reset(us);
789 return USB_STOR_TRANSPORT_FAILED;
790 }
791#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530792 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000793 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
794 printf("ptr[%d] %#x ", index, ptr[index]);
795 printf("\n");
796#endif
797 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530798 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000799 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
800 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530801 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530802 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000803 usb_stor_BBB_reset(us);
804 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530805 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530806 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000807 usb_stor_BBB_reset(us);
808 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530809 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530810 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000811 usb_stor_BBB_reset(us);
812 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530813 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530814 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000815 usb_stor_BBB_reset(us);
816 return USB_STOR_TRANSPORT_FAILED;
817 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530818 debug("transferred %dB instead of %ldB\n",
819 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000820 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530821 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530822 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000823 return USB_STOR_TRANSPORT_FAILED;
824 }
825
826 return result;
827}
828
Simon Glass5fb559d2017-06-14 21:28:30 -0600829static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000830{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100831 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600832 struct scsi_cmd *psrb;
833 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100834 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000835
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200836 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100837 status = USB_STOR_TRANSPORT_GOOD;
838 retry = 0;
839 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000840 /* issue the command */
841do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100842 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530843 debug("command / Data returned %d, status %lX\n",
844 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100846 if (us->protocol == US_PR_CBI) {
847 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000848 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100849 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530850 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000851 return status;
852 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100853 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
854 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
855 if (!us->ip_data) {
856 /* if the status is good, report it */
857 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530858 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000859 return status;
860 }
861 }
862 }
863 /* do we have to issue an auto request? */
864 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100865 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530866 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000867 us->transport_reset(us);
868 return USB_STOR_TRANSPORT_ERROR;
869 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 if ((us->protocol == US_PR_CBI) &&
871 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
872 (srb->cmd[0] == SCSI_INQUIRY))) {
873 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530874 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000875 return USB_STOR_TRANSPORT_GOOD;
876 }
877 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100878 memset(&psrb->cmd[0], 0, 12);
879 psrb->cmd[0] = SCSI_REQ_SENSE;
880 psrb->cmd[1] = srb->lun << 5;
881 psrb->cmd[4] = 18;
882 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200883 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100884 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000885 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100886 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530887 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000888 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100889 if (us->protocol == US_PR_CBI)
890 status = usb_stor_CBI_get_status(psrb, us);
891
892 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530893 debug(" AUTO REQUEST ERROR %ld\n",
894 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000895 return USB_STOR_TRANSPORT_ERROR;
896 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530897 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
898 srb->sense_buf[0], srb->sense_buf[2],
899 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000900 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100901 if ((srb->sense_buf[2] == 0) &&
902 (srb->sense_buf[12] == 0) &&
903 (srb->sense_buf[13] == 0)) {
904 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000905 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 }
907
wdenkaffae2b2002-08-17 09:36:01 +0000908 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100909 switch (srb->sense_buf[2]) {
910 case 0x01:
911 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000912 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000913 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914 case 0x02:
915 /* Not Ready */
916 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
917 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
918 " 0x%02X (NOT READY)\n", srb->cmd[0],
919 srb->sense_buf[0], srb->sense_buf[2],
920 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000921 return USB_STOR_TRANSPORT_FAILED;
922 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000923 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000924 goto do_retry;
925 }
926 break;
927 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100928 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
929 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
930 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
931 srb->sense_buf[2], srb->sense_buf[12],
932 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000933 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100934 } else
wdenkde887eb2003-09-10 18:20:28 +0000935 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000936 break;
wdenkaffae2b2002-08-17 09:36:01 +0000937 }
938 return USB_STOR_TRANSPORT_FAILED;
939}
940
Bin Meng9f447112017-09-07 06:13:21 -0700941static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
942 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700943{
Bin Mengf6e373e2017-09-07 06:13:20 -0700944 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200945 * Limit the total size of a transfer to 120 KB.
946 *
947 * Some devices are known to choke with anything larger. It seems like
948 * the problem stems from the fact that original IDE controllers had
949 * only an 8-bit register to hold the number of sectors in one transfer
950 * and even those couldn't handle a full 256 sectors.
951 *
952 * Because we want to make sure we interoperate with as many devices as
953 * possible, we will maintain a 240 sector transfer size limit for USB
954 * Mass Storage devices.
955 *
956 * Tests show that other operating have similar limits with Microsoft
957 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
958 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
959 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700960 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200961 unsigned short blk = 240;
962
963#if CONFIG_IS_ENABLED(DM_USB)
964 size_t size;
965 int ret;
966
Bin Meng9f447112017-09-07 06:13:21 -0700967 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200968 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700969 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700970#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700971
972 us->max_xfer_blk = blk;
973}
wdenkaffae2b2002-08-17 09:36:01 +0000974
Simon Glass5fb559d2017-06-14 21:28:30 -0600975static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000976{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100977 int retry, i;
978 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000979 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100980 memset(&srb->cmd[0], 0, 12);
981 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200982 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100983 srb->cmd[4] = 36;
984 srb->datalen = 36;
985 srb->cmdlen = 12;
986 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530987 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000989 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200990 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000991
Michael Trimarchi956a4352008-12-10 15:52:06 +0100992 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000993 printf("error in inquiry\n");
994 return -1;
995 }
996 return 0;
997}
998
Simon Glass5fb559d2017-06-14 21:28:30 -0600999static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001000{
1001 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001002
Michael Trimarchi956a4352008-12-10 15:52:06 +01001003 ptr = (char *)srb->pdata;
1004 memset(&srb->cmd[0], 0, 12);
1005 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001006 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001007 srb->cmd[4] = 18;
1008 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001009 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001010 srb->cmdlen = 12;
1011 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301012 debug("Request Sense returned %02X %02X %02X\n",
1013 srb->sense_buf[2], srb->sense_buf[12],
1014 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001015 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001016 return 0;
1017}
1018
Simon Glass5fb559d2017-06-14 21:28:30 -06001019static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001020{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001021 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001022
wdenkaffae2b2002-08-17 09:36:01 +00001023 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001024 memset(&srb->cmd[0], 0, 12);
1025 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001026 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001027 srb->datalen = 0;
1028 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001029 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1030 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001031 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001032 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001033 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001034 /*
1035 * Check the Key Code Qualifier, if it matches
1036 * "Not Ready - medium not present"
1037 * (the sense Key equals 0x2 and the ASC is 0x3a)
1038 * return immediately as the medium being absent won't change
1039 * unless there is a user action.
1040 */
1041 if ((srb->sense_buf[2] == 0x02) &&
1042 (srb->sense_buf[12] == 0x3a))
1043 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001044 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001045 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001046
wdenkaffae2b2002-08-17 09:36:01 +00001047 return -1;
1048}
1049
Simon Glass5fb559d2017-06-14 21:28:30 -06001050static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001051{
1052 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001053 /* XXX retries */
1054 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001055 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001056 memset(&srb->cmd[0], 0, 12);
1057 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001058 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001059 srb->datalen = 8;
1060 srb->cmdlen = 12;
1061 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001062 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001063 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001064
wdenkaffae2b2002-08-17 09:36:01 +00001065 return -1;
1066}
1067
Simon Glass5fb559d2017-06-14 21:28:30 -06001068static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1069 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001070{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001071 memset(&srb->cmd[0], 0, 12);
1072 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001073 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001074 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1075 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1076 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1077 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1078 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1079 srb->cmd[8] = (unsigned char) blocks & 0xff;
1080 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301081 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001082 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001083}
1084
Simon Glass5fb559d2017-06-14 21:28:30 -06001085static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1086 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301087{
1088 memset(&srb->cmd[0], 0, 12);
1089 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001090 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301091 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;
1097 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301098 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301099 return ss->transport(srb, ss);
1100}
1101
wdenkaffae2b2002-08-17 09:36:01 +00001102
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001103#ifdef CONFIG_USB_BIN_FIXUP
1104/*
1105 * Some USB storage devices queried for SCSI identification data respond with
1106 * binary strings, which if output to the console freeze the terminal. The
1107 * workaround is to modify the vendor and product strings read from such
1108 * device with proper values (as reported by 'usb info').
1109 *
1110 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001111 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001112 */
1113static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1114 unsigned char vendor[],
1115 unsigned char product[]) {
1116 const unsigned char max_vendor_len = 40;
1117 const unsigned char max_product_len = 20;
1118 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001119 strncpy((char *)vendor, "SMSC", max_vendor_len);
1120 strncpy((char *)product, "Flash Media Cntrller",
1121 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001122 }
1123}
1124#endif /* CONFIG_USB_BIN_FIXUP */
1125
Sven Schwermerc58ff202018-11-21 08:43:57 +01001126#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001127static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1128 lbaint_t blkcnt, void *buffer)
1129#else
Simon Glasse3394752016-02-29 15:25:34 -07001130static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001131 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001132#endif
wdenkaffae2b2002-08-17 09:36:01 +00001133{
Gabe Black7d077682012-10-12 14:26:07 +00001134 lbaint_t start, blks;
1135 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001136 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001137 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001138 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001139 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001140 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001141#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001142 struct blk_desc *block_dev;
1143#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001144
1145 if (blkcnt == 0)
1146 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001147 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001148#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001149 block_dev = dev_get_uclass_platdata(dev);
1150 udev = dev_get_parent_priv(dev_get_parent(dev));
1151 debug("\nusb_read: udev %d\n", block_dev->devnum);
1152#else
Simon Glass99e598e2016-02-29 15:25:54 -07001153 debug("\nusb_read: udev %d\n", block_dev->devnum);
1154 udev = usb_dev_desc[block_dev->devnum].priv;
1155 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001156 debug("%s: No device\n", __func__);
1157 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001158 }
Simon Glass01f5be92016-02-29 15:25:58 -07001159#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001160 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001161
1162 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001163 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001164 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001165 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001166 start = blknr;
1167 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001168
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001169 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1170 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001171
wdenkaffae2b2002-08-17 09:36:01 +00001172 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001173 /* XXX need some comment here */
1174 retry = 2;
1175 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001176 if (blks > ss->max_xfer_blk)
1177 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001178 else
1179 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001180retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001181 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001182 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001183 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001184 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001185 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301186 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001187 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001188 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001189 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001190 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001191 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001192 break;
1193 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001194 start += smallblks;
1195 blks -= smallblks;
1196 buf_addr += srb->datalen;
1197 } while (blks != 0);
1198
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001199 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301200 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001201
Marek Vasut118a9032020-04-06 14:29:44 +02001202 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001203 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001204 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001205 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001206 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001207}
1208
Sven Schwermerc58ff202018-11-21 08:43:57 +01001209#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001210static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1211 lbaint_t blkcnt, const void *buffer)
1212#else
Simon Glasse3394752016-02-29 15:25:34 -07001213static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001214 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001215#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301216{
Gabe Black7d077682012-10-12 14:26:07 +00001217 lbaint_t start, blks;
1218 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301219 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001220 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001221 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001222 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001223 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001224#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001225 struct blk_desc *block_dev;
1226#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301227
1228 if (blkcnt == 0)
1229 return 0;
1230
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301231 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001232#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001233 block_dev = dev_get_uclass_platdata(dev);
1234 udev = dev_get_parent_priv(dev_get_parent(dev));
1235 debug("\nusb_read: udev %d\n", block_dev->devnum);
1236#else
Simon Glass99e598e2016-02-29 15:25:54 -07001237 debug("\nusb_read: udev %d\n", block_dev->devnum);
1238 udev = usb_dev_desc[block_dev->devnum].priv;
1239 if (!udev) {
1240 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001241 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001242 }
Simon Glass01f5be92016-02-29 15:25:58 -07001243#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001244 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301245
1246 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001247 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301248
Simon Glass99e598e2016-02-29 15:25:54 -07001249 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001250 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301251 start = blknr;
1252 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301253
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001254 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1255 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301256
1257 do {
1258 /* If write fails retry for max retry count else
1259 * return with number of blocks written successfully.
1260 */
1261 retry = 2;
1262 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001263 if (blks > ss->max_xfer_blk)
1264 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301265 else
1266 smallblks = (unsigned short) blks;
1267retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001268 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301269 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001270 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301271 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001272 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301273 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001274 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001275 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301276 if (retry--)
1277 goto retry_it;
1278 blkcnt -= blks;
1279 break;
1280 }
1281 start += smallblks;
1282 blks -= smallblks;
1283 buf_addr += srb->datalen;
1284 } while (blks != 0);
1285
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001286 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1287 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301288
Marek Vasut118a9032020-04-06 14:29:44 +02001289 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301290 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001291 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001292 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301293 return blkcnt;
1294
1295}
wdenkaffae2b2002-08-17 09:36:01 +00001296
1297/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001298int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1299 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001300{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001301 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001302 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301303 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001304 unsigned int flags = 0;
1305
wdenkaffae2b2002-08-17 09:36:01 +00001306 /* let's examine the device now */
1307 iface = &dev->config.if_desc[ifnum];
1308
wdenkaffae2b2002-08-17 09:36:01 +00001309 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001310 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1311 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1312 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001313 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001314 /* if it's not a mass storage, we go no further */
1315 return 0;
1316 }
1317
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001318 memset(ss, 0, sizeof(struct us_data));
1319
wdenkaffae2b2002-08-17 09:36:01 +00001320 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301321 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001322
1323 /* Initialize the us_data structure with some useful info */
1324 ss->flags = flags;
1325 ss->ifnum = ifnum;
1326 ss->pusb_dev = dev;
1327 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001328 ss->subclass = iface->desc.bInterfaceSubClass;
1329 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001330
1331 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301332 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001333 switch (ss->protocol) {
1334 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301335 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001336 ss->transport = usb_stor_CB_transport;
1337 ss->transport_reset = usb_stor_CB_reset;
1338 break;
1339
1340 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301341 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001342 ss->transport = usb_stor_CB_transport;
1343 ss->transport_reset = usb_stor_CB_reset;
1344 break;
wdenkde887eb2003-09-10 18:20:28 +00001345 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301346 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001347 ss->transport = usb_stor_BBB_transport;
1348 ss->transport_reset = usb_stor_BBB_reset;
1349 break;
wdenkaffae2b2002-08-17 09:36:01 +00001350 default:
wdenk5f495752004-02-26 23:46:20 +00001351 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001352 return 0;
1353 break;
1354 }
1355
1356 /*
1357 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1358 * An optional interrupt is OK (necessary for CBI protocol).
1359 * We will ignore any others.
1360 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001361 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301362 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001363 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301364 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001365 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301366 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1367 ss->ep_in = ep_desc->bEndpointAddress &
1368 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001369 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001370 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301371 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001372 USB_ENDPOINT_NUMBER_MASK;
1373 }
1374
1375 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301376 if ((ep_desc->bmAttributes &
1377 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1378 ss->ep_int = ep_desc->bEndpointAddress &
1379 USB_ENDPOINT_NUMBER_MASK;
1380 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001381 }
1382 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301383 debug("Endpoints In %d Out %d Int %d\n",
1384 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001385
1386 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001387 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001388 !ss->ep_in || !ss->ep_out ||
1389 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301390 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001391 return 0;
1392 }
1393 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001394 /* We only handle certain protocols. Currently, these are
1395 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001396 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001397 */
wdenk5f495752004-02-26 23:46:20 +00001398 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1399 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001400 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001401 return 0;
1402 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001403 if (ss->ep_int) {
1404 /* we had found an interrupt endpoint, prepare irq pipe
1405 * set up the IRQ pipe and handler
1406 */
wdenkaffae2b2002-08-17 09:36:01 +00001407 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1408 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1409 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001410 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001411 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001412
1413 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001414 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001415
Michael Trimarchi956a4352008-12-10 15:52:06 +01001416 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001417 return 1;
1418}
1419
Michael Trimarchi956a4352008-12-10 15:52:06 +01001420int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001421 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001422{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001423 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001424 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1425 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1426 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001427 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001428
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001429 pccb->pdata = usb_stor_buf;
1430
1431 dev_desc->target = dev->devnum;
1432 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301433 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001434
Simon Glass78330d62015-03-25 12:22:12 -06001435 if (usb_inquiry(pccb, ss)) {
1436 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001437 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001438 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001439
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001440 perq = usb_stor_buf[0];
1441 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001442
Soeren Moche4828002014-11-08 07:02:14 +01001443 /*
1444 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1445 * they would not respond to test_unit_ready .
1446 */
1447 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001448 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001449 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001450 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001451 if ((modi&0x80) == 0x80) {
1452 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001453 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001454 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001455 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1456 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1457 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001458 dev_desc->vendor[8] = 0;
1459 dev_desc->product[16] = 0;
1460 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001461#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001462 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1463 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001464#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301465 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1466 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001467 if (usb_test_unit_ready(pccb, ss)) {
1468 printf("Device NOT ready\n"
1469 " Request Sense returned %02X %02X %02X\n",
1470 pccb->sense_buf[2], pccb->sense_buf[12],
1471 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001472 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001473 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001474 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001475 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001476 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001477 memset(pccb->pdata, 0, 8);
1478 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001479 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001480 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001481 cap[0] = 2880;
1482 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001483 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001484 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001485#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001486 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1487 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001488
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001489 cap[0] = cpu_to_be32(cap[0]);
1490 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001491#endif
1492
1493 capacity = be32_to_cpu(cap[0]) + 1;
1494 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001495
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001496 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1497 dev_desc->lba = capacity;
1498 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001499 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001500 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301501 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001502
wdenkaffae2b2002-08-17 09:36:01 +00001503 return 1;
1504}
Simon Glassac9774e2015-03-25 12:22:16 -06001505
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001506#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001507
1508static int usb_mass_storage_probe(struct udevice *dev)
1509{
Simon Glassde44acf2015-09-28 23:32:01 -06001510 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001511 int ret;
1512
1513 usb_disable_asynch(1); /* asynch transfer not allowed */
1514 ret = usb_stor_probe_device(udev);
1515 usb_disable_asynch(0); /* asynch transfer allowed */
1516
1517 return ret;
1518}
1519
1520static const struct udevice_id usb_mass_storage_ids[] = {
1521 { .compatible = "usb-mass-storage" },
1522 { }
1523};
1524
1525U_BOOT_DRIVER(usb_mass_storage) = {
1526 .name = "usb_mass_storage",
1527 .id = UCLASS_MASS_STORAGE,
1528 .of_match = usb_mass_storage_ids,
1529 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001530#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001531 .platdata_auto_alloc_size = sizeof(struct us_data),
1532#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001533};
1534
1535UCLASS_DRIVER(usb_mass_storage) = {
1536 .id = UCLASS_MASS_STORAGE,
1537 .name = "usb_mass_storage",
1538};
1539
1540static const struct usb_device_id mass_storage_id_table[] = {
1541 {
1542 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1543 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1544 },
1545 { } /* Terminating entry */
1546};
1547
Simon Glass46952fb2015-07-06 16:47:51 -06001548U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001549#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001550
Sven Schwermerc58ff202018-11-21 08:43:57 +01001551#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001552static const struct blk_ops usb_storage_ops = {
1553 .read = usb_stor_read,
1554 .write = usb_stor_write,
1555};
1556
1557U_BOOT_DRIVER(usb_storage_blk) = {
1558 .name = "usb_storage_blk",
1559 .id = UCLASS_BLK,
1560 .ops = &usb_storage_ops,
1561};
Simon Glassd3171412016-05-01 11:36:06 -06001562#else
1563U_BOOT_LEGACY_BLK(usb) = {
1564 .if_typename = "usb",
1565 .if_type = IF_TYPE_USB,
1566 .max_devs = USB_MAX_STOR_DEV,
1567 .desc = usb_dev_desc,
1568};
Simon Glassac9774e2015-03-25 12:22:16 -06001569#endif