blob: 54f8e53c63076cec6dc5a5ba27b746c9edec1908 [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>
36#include <command.h>
Simon Glassac9774e2015-03-25 12:22:16 -060037#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060038#include <errno.h>
Simon Glass332a9b62015-03-25 12:22:14 -060039#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060040#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020041#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000042#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060043#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070044#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000045
Grant Likelyffc2dd72007-02-20 09:04:34 +010046#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000047#include <usb.h>
48
wdenk5f495752004-02-26 23:46:20 +000049#undef BBB_COMDAT_TRACE
50#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000051
wdenkaffae2b2002-08-17 09:36:01 +000052#include <scsi.h>
53/* direction table -- this indicates the direction of the data
54 * transfer for each command code -- a 1 indicates input
55 */
Mike Frysinger165522b2010-10-20 07:16:04 -040056static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000057 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
58 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
61};
62#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
63
Simon Glass5fb559d2017-06-14 21:28:30 -060064static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010065static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000066
Michael Trimarchi956a4352008-12-10 15:52:06 +010067static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000068
Sven Schwermerc58ff202018-11-21 08:43:57 +010069#if !CONFIG_IS_ENABLED(BLK)
Simon Glasse3394752016-02-29 15:25:34 -070070static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070071#endif
wdenkaffae2b2002-08-17 09:36:01 +000072
73struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060074typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010075typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000076
77struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010078 struct usb_device *pusb_dev; /* this usb_device */
79
80 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020081# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010082 unsigned char ifnum; /* interface number */
83 unsigned char ep_in; /* in endpoint */
84 unsigned char ep_out; /* out ....... */
85 unsigned char ep_int; /* interrupt . */
86 unsigned char subclass; /* as in overview */
87 unsigned char protocol; /* .............. */
88 unsigned char attention_done; /* force attn on first cmd */
89 unsigned short ip_data; /* interrupt data */
90 int action; /* what to do */
91 int ip_wanted; /* needed */
92 int *irq_handle; /* for USB int requests */
93 unsigned int irqpipe; /* pipe for release_irq */
94 unsigned char irqmaxp; /* max packed for irq Pipe */
95 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -060096 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +010097 trans_reset transport_reset; /* reset routine */
98 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -070099 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000100};
101
Sven Schwermerc58ff202018-11-21 08:43:57 +0100102#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000103static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700104#endif
wdenkaffae2b2002-08-17 09:36:01 +0000105
wdenk5f495752004-02-26 23:46:20 +0000106#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000107#define USB_STOR_TRANSPORT_FAILED -1
108#define USB_STOR_TRANSPORT_ERROR -2
109
Michael Trimarchi956a4352008-12-10 15:52:06 +0100110int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700111 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100112int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
113 struct us_data *ss);
Sven Schwermerc58ff202018-11-21 08:43:57 +0100114#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700115static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
116 lbaint_t blkcnt, void *buffer);
117static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
118 lbaint_t blkcnt, const void *buffer);
119#else
Simon Glasse3394752016-02-29 15:25:34 -0700120static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700121 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700122static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700123 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700124#endif
wdenkaffae2b2002-08-17 09:36:01 +0000125void uhci_show_temp_int_td(void);
126
Kim Phillipsb052b602012-10-29 13:34:32 +0000127static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000128{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200129 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000130}
131
Michael Trimarchi956a4352008-12-10 15:52:06 +0100132/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200133 * show info on storage devices; 'usb start/init' must be invoked earlier
134 * as we only retrieve structures populated during devices initialization
135 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100136int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200137{
Simon Glass99e598e2016-02-29 15:25:54 -0700138 int count = 0;
Sven Schwermerc58ff202018-11-21 08:43:57 +0100139#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700140 struct udevice *dev;
141
142 for (blk_first_device(IF_TYPE_USB, &dev);
143 dev;
144 blk_next_device(&dev)) {
145 struct blk_desc *desc = dev_get_uclass_platdata(dev);
146
147 printf(" Device %d: ", desc->devnum);
148 dev_print(desc);
149 count++;
150 }
151#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200152 int i;
153
Aras Vaichas7ede1862008-03-25 12:09:07 +1100154 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200155 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100156 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200157 dev_print(&usb_dev_desc[i]);
158 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100159 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100160 }
Simon Glass01f5be92016-02-29 15:25:58 -0700161#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700162 if (!count) {
163 printf("No storage devices, perhaps not 'usb start'ed..?\n");
164 return 1;
165 }
166
Simon Glass8c6c0742016-03-16 07:45:44 -0600167 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200168}
169
Ludovic Courtès134396c2010-10-05 22:04:26 +0200170static unsigned int usb_get_max_lun(struct us_data *us)
171{
172 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530173 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200174 len = usb_control_msg(us->pusb_dev,
175 usb_rcvctrlpipe(us->pusb_dev, 0),
176 US_BBB_GET_MAX_LUN,
177 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
178 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530179 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200180 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530181 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530182 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200183}
184
Simon Glass99e598e2016-02-29 15:25:54 -0700185static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600186{
Simon Glass99e598e2016-02-29 15:25:54 -0700187 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700188
Sven Schwermerc58ff202018-11-21 08:43:57 +0100189#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700190 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700191 int ret;
192#else
Simon Glass99e598e2016-02-29 15:25:54 -0700193 int start;
194
195 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600196 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700197#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600198
Simon Glass01f5be92016-02-29 15:25:58 -0700199 debug("\n\nProbing for storage\n");
Sven Schwermerc58ff202018-11-21 08:43:57 +0100200#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700201 /*
202 * We store the us_data in the mass storage device's platdata. It
203 * is shared by all LUNs (block devices) attached to this mass storage
204 * device.
205 */
206 data = dev_get_platdata(udev->dev);
207 if (!usb_storage_probe(udev, 0, data))
208 return 0;
209 max_lun = usb_get_max_lun(data);
210 for (lun = 0; lun <= max_lun; lun++) {
211 struct blk_desc *blkdev;
212 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600213 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700214
Simon Glass966b6952016-05-01 11:36:29 -0600215 snprintf(str, sizeof(str), "lun%d", lun);
216 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
217 IF_TYPE_USB, usb_max_devs, 512, 0,
218 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700219 if (ret) {
220 debug("Cannot bind driver\n");
221 return ret;
222 }
223
224 blkdev = dev_get_uclass_platdata(dev);
225 blkdev->target = 0xff;
226 blkdev->lun = lun;
227
228 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengcbc3da82018-10-15 02:21:07 -0700229 if (ret == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700230 usb_max_devs++;
231 debug("%s: Found device %p\n", __func__, udev);
232 } else {
233 debug("usb_stor_get_info: Invalid device\n");
234 ret = device_unbind(dev);
235 if (ret)
236 return ret;
237 }
238 }
239#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700240 /* We don't have space to even probe if we hit the maximum */
241 if (usb_max_devs == USB_MAX_STOR_DEV) {
242 printf("max USB Storage Device reached: %d stopping\n",
243 usb_max_devs);
244 return -ENOSPC;
245 }
246
Simon Glass99e598e2016-02-29 15:25:54 -0700247 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
248 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600249
Simon Glass99e598e2016-02-29 15:25:54 -0700250 /*
251 * OK, it's a storage device. Iterate over its LUNs and populate
252 * usb_dev_desc'
253 */
254 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600255
Simon Glass99e598e2016-02-29 15:25:54 -0700256 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
257 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
258 lun++) {
259 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600260
Simon Glass99e598e2016-02-29 15:25:54 -0700261 blkdev = &usb_dev_desc[usb_max_devs];
262 memset(blkdev, '\0', sizeof(struct blk_desc));
263 blkdev->if_type = IF_TYPE_USB;
264 blkdev->devnum = usb_max_devs;
265 blkdev->part_type = PART_TYPE_UNKNOWN;
266 blkdev->target = 0xff;
267 blkdev->type = DEV_TYPE_UNKNOWN;
268 blkdev->block_read = usb_stor_read;
269 blkdev->block_write = usb_stor_write;
270 blkdev->lun = lun;
271 blkdev->priv = udev;
272
273 if (usb_stor_get_info(udev, &usb_stor[start],
274 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700275 debug("partype: %d\n", blkdev->part_type);
276 part_init(blkdev);
277 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700278 usb_max_devs++;
279 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600280 }
281 }
Simon Glass01f5be92016-02-29 15:25:58 -0700282#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600283
Simon Glassdf7d34f2015-03-25 12:22:15 -0600284 return 0;
285}
286
287void usb_stor_reset(void)
288{
289 usb_max_devs = 0;
290}
291
Michael Trimarchi956a4352008-12-10 15:52:06 +0100292/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200293 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000294 * to the user if mode = 1
295 * returns current device or -1 if no
296 */
297int usb_stor_scan(int mode)
298{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100299 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200300 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100301
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100302#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100303 unsigned char i;
304
wdenkaffae2b2002-08-17 09:36:01 +0000305 usb_disable_asynch(1); /* asynch transfer not allowed */
306
Simon Glassdf7d34f2015-03-25 12:22:15 -0600307 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100308 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600309 struct usb_device *dev;
310
Michael Trimarchi956a4352008-12-10 15:52:06 +0100311 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530312 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600313 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000314 break;
wdenkaffae2b2002-08-17 09:36:01 +0000315 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200316
wdenkaffae2b2002-08-17 09:36:01 +0000317 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100318#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200319 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100320 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000321 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100322 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000323}
324
325static int usb_stor_irq(struct usb_device *dev)
326{
327 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100328 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000329
Michael Trimarchi956a4352008-12-10 15:52:06 +0100330 if (us->ip_wanted)
331 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000332 return 0;
333}
334
335
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530336#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000337
Simon Glass5fb559d2017-06-14 21:28:30 -0600338static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000339{
340 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100341 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
342 for (i = 0; i < 12; i++)
343 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000344 printf("\n");
345}
346
347static void display_int_status(unsigned long tmp)
348{
349 printf("Status: %s %s %s %s %s %s %s\n",
350 (tmp & USB_ST_ACTIVE) ? "Active" : "",
351 (tmp & USB_ST_STALLED) ? "Stalled" : "",
352 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
353 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
354 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
355 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
356 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
357}
358#endif
359/***********************************************************************
360 * Data transfer routines
361 ***********************************************************************/
362
363static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
364{
365 int max_size;
366 int this_xfer;
367 int result;
368 int partial;
369 int maxtry;
370 int stat;
371
372 /* determine the maximum packet size for these transfers */
373 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
374
375 /* while we have data left to transfer */
376 while (length) {
377
378 /* calculate how long this will be -- maximum or a remainder */
379 this_xfer = length > max_size ? max_size : length;
380 length -= this_xfer;
381
382 /* setup the retry counter */
383 maxtry = 10;
384
385 /* set up the transfer loop */
386 do {
387 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600388 debug("Bulk xfer 0x%lx(%d) try #%d\n",
389 (ulong)map_to_sysmem(buf), this_xfer,
390 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000391 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100392 this_xfer, &partial,
393 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530394 debug("bulk_msg returned %d xferred %d/%d\n",
395 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100396 if (us->pusb_dev->status != 0) {
397 /* if we stall, we need to clear it before
398 * we go on
399 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530400#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000401 display_int_status(us->pusb_dev->status);
402#endif
403 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530404 debug("stalled ->clearing endpoint" \
405 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000406 stat = us->pusb_dev->status;
407 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100408 us->pusb_dev->status = stat;
409 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530410 debug("bulk transferred" \
411 "with error %lX," \
412 " but data ok\n",
413 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000414 return 0;
415 }
416 else
417 return result;
418 }
419 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530420 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000421 return result;
422 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530423 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100424 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530425 debug(" %ld, but data ok\n",
426 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000427 return 0;
428 }
429 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530430 debug(" %ld, data %d\n",
431 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000432 if (!maxtry--)
433 return result;
434 }
435 /* update to show what data was transferred */
436 this_xfer -= partial;
437 buf += partial;
438 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100439 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000440 }
441
442 /* if we get here, we're done and successful */
443 return 0;
444}
445
wdenkde887eb2003-09-10 18:20:28 +0000446static int usb_stor_BBB_reset(struct us_data *us)
447{
448 int result;
449 unsigned int pipe;
450
451 /*
452 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
453 *
454 * For Reset Recovery the host shall issue in the following order:
455 * a) a Bulk-Only Mass Storage Reset
456 * b) a Clear Feature HALT to the Bulk-In endpoint
457 * c) a Clear Feature HALT to the Bulk-Out endpoint
458 *
459 * This is done in 3 steps.
460 *
461 * If the reset doesn't succeed, the device should be port reset.
462 *
463 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
464 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530465 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100466 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
467 US_BBB_RESET,
468 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000469 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200470
Michael Trimarchi956a4352008-12-10 15:52:06 +0100471 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530472 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000473 return -1;
474 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200475
wdenkde887eb2003-09-10 18:20:28 +0000476 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000477 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530478 debug("BBB_reset result %d: status %lX reset\n",
479 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000480 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
481 result = usb_clear_halt(us->pusb_dev, pipe);
482 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000483 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530484 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
485 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000486 /* long wait for reset */
487 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
488 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000489 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530490 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
491 result, us->pusb_dev->status);
492 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000493 return 0;
494}
495
wdenkaffae2b2002-08-17 09:36:01 +0000496/* FIXME: this reset function doesn't really reset the port, and it
497 * should. Actually it should probably do what it's doing here, and
498 * reset the port physically
499 */
500static int usb_stor_CB_reset(struct us_data *us)
501{
502 unsigned char cmd[12];
503 int result;
504
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530505 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100506 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000507 cmd[0] = SCSI_SEND_DIAG;
508 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100509 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
510 US_CBI_ADSC,
511 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
512 0, us->ifnum, cmd, sizeof(cmd),
513 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000514
515 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000516 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530517 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
518 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000519 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
520 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
521
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530522 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000523 return 0;
524}
525
wdenkde887eb2003-09-10 18:20:28 +0000526/*
527 * Set up the command for a BBB device. Note that the actual SCSI
528 * command is copied into cbw.CBWCDB.
529 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600530static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000531{
532 int result;
533 int actlen;
534 int dir_in;
535 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600536 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000537
538 dir_in = US_DIRECTION(srb->cmd[0]);
539
540#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530541 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100542 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
543 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000544 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100545 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000546 printf("cmd[%d] %#x ", result, srb->cmd[result]);
547 printf("\n");
548 }
549#endif
550 /* sanity checks */
551 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530552 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000553 return -1;
554 }
555
556 /* always OUT to the ep */
557 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
558
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530559 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
560 cbw->dCBWTag = cpu_to_le32(CBWTag++);
561 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
562 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
563 cbw->bCBWLUN = srb->lun;
564 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000565 /* copy the command data into the CBW command data buffer */
566 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300567
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530568 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
569 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100570 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000571 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530572 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000573 return result;
574}
575
wdenkaffae2b2002-08-17 09:36:01 +0000576/* FIXME: we also need a CBI_command which sets up the completion
577 * interrupt, and waits for it
578 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600579static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000580{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200581 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100582 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000583 unsigned int pipe;
584 unsigned long status;
585
Michael Trimarchi956a4352008-12-10 15:52:06 +0100586 retry = 5;
587 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000588
Michael Trimarchi956a4352008-12-10 15:52:06 +0100589 if (dir_in)
590 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
591 else
592 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
593
594 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530595 debug("CBI gets a command: Try %d\n", 5 - retry);
596#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000597 usb_show_srb(srb);
598#endif
599 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100600 result = usb_control_msg(us->pusb_dev,
601 usb_sndctrlpipe(us->pusb_dev , 0),
602 US_CBI_ADSC,
603 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000604 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100605 srb->cmd, srb->cmdlen,
606 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530607 debug("CB_transport: control msg returned %d, status %lX\n",
608 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000609 /* check the return code for the command */
610 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100611 if (us->pusb_dev->status & USB_ST_STALLED) {
612 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530613 debug(" stall during command found," \
614 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100615 usb_clear_halt(us->pusb_dev,
616 usb_sndctrlpipe(us->pusb_dev, 0));
617 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000618 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530619 debug(" error during command %02X" \
620 " Stat = %lX\n", srb->cmd[0],
621 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000622 return result;
623 }
624 /* transfer the data payload for this command, if one exists*/
625
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530626 debug("CB_transport: control msg returned %d," \
627 " direction is %s to go 0x%lx\n", result,
628 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000629 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100630 result = us_one_transfer(us, pipe, (char *)srb->pdata,
631 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530632 debug("CBI attempted to transfer data," \
633 " result is %d status %lX, len %d\n",
634 result, us->pusb_dev->status,
635 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100636 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000637 break;
638 } /* if (srb->datalen) */
639 else
640 break;
641 }
642 /* return result */
643
644 return result;
645}
646
647
Simon Glass5fb559d2017-06-14 21:28:30 -0600648static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000649{
650 int timeout;
651
wdenk5f495752004-02-26 23:46:20 +0000652 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200653 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200654 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000655 timeout = 1000;
656 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300657 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000658 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000659 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000660 }
661 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100662 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000663 us->ip_wanted = 0;
664 return USB_STOR_TRANSPORT_ERROR;
665 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700666 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530667 us->ip_data, us->pusb_dev->irq_act_len,
668 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000669 /* UFI gives us ASC and ASCQ, like a request sense */
670 if (us->subclass == US_SC_UFI) {
671 if (srb->cmd[0] == SCSI_REQ_SENSE ||
672 srb->cmd[0] == SCSI_INQUIRY)
673 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000674 else if (us->ip_data)
675 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000676 else
wdenk5f495752004-02-26 23:46:20 +0000677 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000678 }
679 /* otherwise, we interpret the data normally */
680 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000681 case 0x0001:
682 return USB_STOR_TRANSPORT_GOOD;
683 case 0x0002:
684 return USB_STOR_TRANSPORT_FAILED;
685 default:
686 return USB_STOR_TRANSPORT_ERROR;
687 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000688 return USB_STOR_TRANSPORT_ERROR;
689}
690
691#define USB_TRANSPORT_UNKNOWN_RETRY 5
692#define USB_TRANSPORT_NOT_READY_RETRY 10
693
wdenkde887eb2003-09-10 18:20:28 +0000694/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000695static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000696{
wdenkde887eb2003-09-10 18:20:28 +0000697 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900698 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
699 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
700 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000701}
702
Simon Glass5fb559d2017-06-14 21:28:30 -0600703static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000704{
705 int result, retry;
706 int dir_in;
707 int actlen, data_actlen;
708 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600709 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000710#ifdef BBB_XPORT_TRACE
711 unsigned char *ptr;
712 int index;
713#endif
714
715 dir_in = US_DIRECTION(srb->cmd[0]);
716
717 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530718 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000719 result = usb_stor_BBB_comdat(srb, us);
720 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530721 debug("failed to send CBW status %ld\n",
722 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000723 usb_stor_BBB_reset(us);
724 return USB_STOR_TRANSPORT_FAILED;
725 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200726 if (!(us->flags & USB_READY))
727 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000728 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
729 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
730 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000731 data_actlen = 0;
732 /* no data, go immediately to the STATUS phase */
733 if (srb->datalen == 0)
734 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530735 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000736 if (dir_in)
737 pipe = pipein;
738 else
739 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300740
Michael Trimarchi956a4352008-12-10 15:52:06 +0100741 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
742 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000743 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100744 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530745 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000746 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100747 result = usb_stor_BBB_clear_endpt_stall(us,
748 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000749 if (result >= 0)
750 /* continue on to STATUS phase */
751 goto st;
752 }
753 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530754 debug("usb_bulk_msg error status %ld\n",
755 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000756 usb_stor_BBB_reset(us);
757 return USB_STOR_TRANSPORT_FAILED;
758 }
759#ifdef BBB_XPORT_TRACE
760 for (index = 0; index < data_actlen; index++)
761 printf("pdata[%d] %#x ", index, srb->pdata[index]);
762 printf("\n");
763#endif
764 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100765st:
wdenkde887eb2003-09-10 18:20:28 +0000766 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100767again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530768 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530769 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200770 &actlen, USB_CNTL_TIMEOUT*5);
771
wdenkde887eb2003-09-10 18:20:28 +0000772 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100773 if ((result < 0) && (retry < 1) &&
774 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530775 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000776 /* clear the STALL on the endpoint */
777 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
778 if (result >= 0 && (retry++ < 1))
779 /* do a retry */
780 goto again;
781 }
782 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530783 debug("usb_bulk_msg error status %ld\n",
784 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000785 usb_stor_BBB_reset(us);
786 return USB_STOR_TRANSPORT_FAILED;
787 }
788#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530789 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000790 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
791 printf("ptr[%d] %#x ", index, ptr[index]);
792 printf("\n");
793#endif
794 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530795 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000796 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
797 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530798 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530799 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000800 usb_stor_BBB_reset(us);
801 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530802 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530803 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000804 usb_stor_BBB_reset(us);
805 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530806 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530807 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000808 usb_stor_BBB_reset(us);
809 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530810 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530811 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000812 usb_stor_BBB_reset(us);
813 return USB_STOR_TRANSPORT_FAILED;
814 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530815 debug("transferred %dB instead of %ldB\n",
816 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000817 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530818 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530819 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000820 return USB_STOR_TRANSPORT_FAILED;
821 }
822
823 return result;
824}
825
Simon Glass5fb559d2017-06-14 21:28:30 -0600826static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000827{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100828 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600829 struct scsi_cmd *psrb;
830 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100831 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000832
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200833 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100834 status = USB_STOR_TRANSPORT_GOOD;
835 retry = 0;
836 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000837 /* issue the command */
838do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100839 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530840 debug("command / Data returned %d, status %lX\n",
841 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000842 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100843 if (us->protocol == US_PR_CBI) {
844 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100846 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530847 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000848 return status;
849 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100850 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
851 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
852 if (!us->ip_data) {
853 /* if the status is good, report it */
854 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530855 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000856 return status;
857 }
858 }
859 }
860 /* do we have to issue an auto request? */
861 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100862 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530863 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000864 us->transport_reset(us);
865 return USB_STOR_TRANSPORT_ERROR;
866 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100867 if ((us->protocol == US_PR_CBI) &&
868 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
869 (srb->cmd[0] == SCSI_INQUIRY))) {
870 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530871 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000872 return USB_STOR_TRANSPORT_GOOD;
873 }
874 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100875 memset(&psrb->cmd[0], 0, 12);
876 psrb->cmd[0] = SCSI_REQ_SENSE;
877 psrb->cmd[1] = srb->lun << 5;
878 psrb->cmd[4] = 18;
879 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200880 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000882 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100883 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530884 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000885 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100886 if (us->protocol == US_PR_CBI)
887 status = usb_stor_CBI_get_status(psrb, us);
888
889 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530890 debug(" AUTO REQUEST ERROR %ld\n",
891 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000892 return USB_STOR_TRANSPORT_ERROR;
893 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530894 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
895 srb->sense_buf[0], srb->sense_buf[2],
896 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000897 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100898 if ((srb->sense_buf[2] == 0) &&
899 (srb->sense_buf[12] == 0) &&
900 (srb->sense_buf[13] == 0)) {
901 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000902 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903 }
904
wdenkaffae2b2002-08-17 09:36:01 +0000905 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 switch (srb->sense_buf[2]) {
907 case 0x01:
908 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000909 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000910 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 case 0x02:
912 /* Not Ready */
913 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
914 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
915 " 0x%02X (NOT READY)\n", srb->cmd[0],
916 srb->sense_buf[0], srb->sense_buf[2],
917 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000918 return USB_STOR_TRANSPORT_FAILED;
919 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000920 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000921 goto do_retry;
922 }
923 break;
924 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100925 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
926 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
927 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
928 srb->sense_buf[2], srb->sense_buf[12],
929 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000930 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100931 } else
wdenkde887eb2003-09-10 18:20:28 +0000932 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000933 break;
wdenkaffae2b2002-08-17 09:36:01 +0000934 }
935 return USB_STOR_TRANSPORT_FAILED;
936}
937
Bin Meng9f447112017-09-07 06:13:21 -0700938static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
939 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700940{
941 unsigned short blk;
Bin Meng9f447112017-09-07 06:13:21 -0700942 size_t __maybe_unused size;
943 int __maybe_unused ret;
Bin Mengf6e373e2017-09-07 06:13:20 -0700944
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100945#if !CONFIG_IS_ENABLED(DM_USB)
Bin Mengf6e373e2017-09-07 06:13:20 -0700946#ifdef CONFIG_USB_EHCI_HCD
947 /*
948 * The U-Boot EHCI driver can handle any transfer length as long as
949 * there is enough free heap space left, but the SCSI READ(10) and
950 * WRITE(10) commands are limited to 65535 blocks.
951 */
952 blk = USHRT_MAX;
953#else
954 blk = 20;
955#endif
Bin Meng9f447112017-09-07 06:13:21 -0700956#else
957 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
958 if (ret < 0) {
959 /* unimplemented, let's use default 20 */
960 blk = 20;
961 } else {
962 if (size > USHRT_MAX * 512)
Bin Meng77f871b2017-09-27 21:50:07 -0700963 size = USHRT_MAX * 512;
Bin Meng9f447112017-09-07 06:13:21 -0700964 blk = size / 512;
965 }
966#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700967
968 us->max_xfer_blk = blk;
969}
wdenkaffae2b2002-08-17 09:36:01 +0000970
Simon Glass5fb559d2017-06-14 21:28:30 -0600971static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000972{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100973 int retry, i;
974 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000975 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100976 memset(&srb->cmd[0], 0, 12);
977 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200978 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100979 srb->cmd[4] = 36;
980 srb->datalen = 36;
981 srb->cmdlen = 12;
982 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530983 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100984 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000985 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200986 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000987
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000989 printf("error in inquiry\n");
990 return -1;
991 }
992 return 0;
993}
994
Simon Glass5fb559d2017-06-14 21:28:30 -0600995static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000996{
997 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000998
Michael Trimarchi956a4352008-12-10 15:52:06 +0100999 ptr = (char *)srb->pdata;
1000 memset(&srb->cmd[0], 0, 12);
1001 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001002 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001003 srb->cmd[4] = 18;
1004 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001005 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001006 srb->cmdlen = 12;
1007 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301008 debug("Request Sense returned %02X %02X %02X\n",
1009 srb->sense_buf[2], srb->sense_buf[12],
1010 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001011 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001012 return 0;
1013}
1014
Simon Glass5fb559d2017-06-14 21:28:30 -06001015static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001016{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001017 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001018
wdenkaffae2b2002-08-17 09:36:01 +00001019 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001020 memset(&srb->cmd[0], 0, 12);
1021 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001022 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001023 srb->datalen = 0;
1024 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001025 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1026 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001027 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001028 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001029 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001030 /*
1031 * Check the Key Code Qualifier, if it matches
1032 * "Not Ready - medium not present"
1033 * (the sense Key equals 0x2 and the ASC is 0x3a)
1034 * return immediately as the medium being absent won't change
1035 * unless there is a user action.
1036 */
1037 if ((srb->sense_buf[2] == 0x02) &&
1038 (srb->sense_buf[12] == 0x3a))
1039 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001040 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001041 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001042
wdenkaffae2b2002-08-17 09:36:01 +00001043 return -1;
1044}
1045
Simon Glass5fb559d2017-06-14 21:28:30 -06001046static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001047{
1048 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049 /* XXX retries */
1050 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001051 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001052 memset(&srb->cmd[0], 0, 12);
1053 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001054 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001055 srb->datalen = 8;
1056 srb->cmdlen = 12;
1057 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001058 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001059 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001060
wdenkaffae2b2002-08-17 09:36:01 +00001061 return -1;
1062}
1063
Simon Glass5fb559d2017-06-14 21:28:30 -06001064static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1065 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001066{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001067 memset(&srb->cmd[0], 0, 12);
1068 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001069 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001070 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1071 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1072 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1073 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1074 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1075 srb->cmd[8] = (unsigned char) blocks & 0xff;
1076 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301077 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001078 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001079}
1080
Simon Glass5fb559d2017-06-14 21:28:30 -06001081static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1082 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301083{
1084 memset(&srb->cmd[0], 0, 12);
1085 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001086 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301087 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1088 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1089 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1090 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1091 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1092 srb->cmd[8] = (unsigned char) blocks & 0xff;
1093 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301094 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301095 return ss->transport(srb, ss);
1096}
1097
wdenkaffae2b2002-08-17 09:36:01 +00001098
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001099#ifdef CONFIG_USB_BIN_FIXUP
1100/*
1101 * Some USB storage devices queried for SCSI identification data respond with
1102 * binary strings, which if output to the console freeze the terminal. The
1103 * workaround is to modify the vendor and product strings read from such
1104 * device with proper values (as reported by 'usb info').
1105 *
1106 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001107 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001108 */
1109static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1110 unsigned char vendor[],
1111 unsigned char product[]) {
1112 const unsigned char max_vendor_len = 40;
1113 const unsigned char max_product_len = 20;
1114 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001115 strncpy((char *)vendor, "SMSC", max_vendor_len);
1116 strncpy((char *)product, "Flash Media Cntrller",
1117 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001118 }
1119}
1120#endif /* CONFIG_USB_BIN_FIXUP */
1121
Sven Schwermerc58ff202018-11-21 08:43:57 +01001122#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001123static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1124 lbaint_t blkcnt, void *buffer)
1125#else
Simon Glasse3394752016-02-29 15:25:34 -07001126static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001127 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001128#endif
wdenkaffae2b2002-08-17 09:36:01 +00001129{
Gabe Black7d077682012-10-12 14:26:07 +00001130 lbaint_t start, blks;
1131 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001132 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001133 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001134 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001135 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001136 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001137#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001138 struct blk_desc *block_dev;
1139#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001140
1141 if (blkcnt == 0)
1142 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001143 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001144#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001145 block_dev = dev_get_uclass_platdata(dev);
1146 udev = dev_get_parent_priv(dev_get_parent(dev));
1147 debug("\nusb_read: udev %d\n", block_dev->devnum);
1148#else
Simon Glass99e598e2016-02-29 15:25:54 -07001149 debug("\nusb_read: udev %d\n", block_dev->devnum);
1150 udev = usb_dev_desc[block_dev->devnum].priv;
1151 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001152 debug("%s: No device\n", __func__);
1153 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001154 }
Simon Glass01f5be92016-02-29 15:25:58 -07001155#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001156 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001157
1158 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass99e598e2016-02-29 15:25:54 -07001159 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001160 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001161 start = blknr;
1162 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001163
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001164 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1165 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001166
wdenkaffae2b2002-08-17 09:36:01 +00001167 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001168 /* XXX need some comment here */
1169 retry = 2;
1170 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001171 if (blks > ss->max_xfer_blk)
1172 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001173 else
1174 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001175retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001176 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001177 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001178 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001179 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001180 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301181 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001182 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001183 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001184 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001185 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001186 break;
1187 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001188 start += smallblks;
1189 blks -= smallblks;
1190 buf_addr += srb->datalen;
1191 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001192 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001193
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001194 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301195 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001196
wdenkaffae2b2002-08-17 09:36:01 +00001197 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001198 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001199 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001200 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001201}
1202
Sven Schwermerc58ff202018-11-21 08:43:57 +01001203#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001204static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1205 lbaint_t blkcnt, const void *buffer)
1206#else
Simon Glasse3394752016-02-29 15:25:34 -07001207static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001208 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001209#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301210{
Gabe Black7d077682012-10-12 14:26:07 +00001211 lbaint_t start, blks;
1212 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301213 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001214 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001215 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001216 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001217 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001218#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001219 struct blk_desc *block_dev;
1220#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301221
1222 if (blkcnt == 0)
1223 return 0;
1224
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301225 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001226#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001227 block_dev = dev_get_uclass_platdata(dev);
1228 udev = dev_get_parent_priv(dev_get_parent(dev));
1229 debug("\nusb_read: udev %d\n", block_dev->devnum);
1230#else
Simon Glass99e598e2016-02-29 15:25:54 -07001231 debug("\nusb_read: udev %d\n", block_dev->devnum);
1232 udev = usb_dev_desc[block_dev->devnum].priv;
1233 if (!udev) {
1234 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001235 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001236 }
Simon Glass01f5be92016-02-29 15:25:58 -07001237#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001238 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301239
1240 usb_disable_asynch(1); /* asynch transfer not allowed */
1241
Simon Glass99e598e2016-02-29 15:25:54 -07001242 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001243 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301244 start = blknr;
1245 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301246
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001247 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1248 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301249
1250 do {
1251 /* If write fails retry for max retry count else
1252 * return with number of blocks written successfully.
1253 */
1254 retry = 2;
1255 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001256 if (blks > ss->max_xfer_blk)
1257 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301258 else
1259 smallblks = (unsigned short) blks;
1260retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001261 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301262 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001263 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301264 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001265 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301266 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001267 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301268 if (retry--)
1269 goto retry_it;
1270 blkcnt -= blks;
1271 break;
1272 }
1273 start += smallblks;
1274 blks -= smallblks;
1275 buf_addr += srb->datalen;
1276 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001277 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301278
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001279 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1280 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301281
1282 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001283 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001284 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301285 return blkcnt;
1286
1287}
wdenkaffae2b2002-08-17 09:36:01 +00001288
1289/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001290int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1291 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001292{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001293 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001294 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301295 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001296 unsigned int flags = 0;
1297
wdenkaffae2b2002-08-17 09:36:01 +00001298 /* let's examine the device now */
1299 iface = &dev->config.if_desc[ifnum];
1300
wdenkaffae2b2002-08-17 09:36:01 +00001301 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001302 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1303 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1304 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001305 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001306 /* if it's not a mass storage, we go no further */
1307 return 0;
1308 }
1309
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001310 memset(ss, 0, sizeof(struct us_data));
1311
wdenkaffae2b2002-08-17 09:36:01 +00001312 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301313 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001314
1315 /* Initialize the us_data structure with some useful info */
1316 ss->flags = flags;
1317 ss->ifnum = ifnum;
1318 ss->pusb_dev = dev;
1319 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001320 ss->subclass = iface->desc.bInterfaceSubClass;
1321 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001322
1323 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301324 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001325 switch (ss->protocol) {
1326 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301327 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001328 ss->transport = usb_stor_CB_transport;
1329 ss->transport_reset = usb_stor_CB_reset;
1330 break;
1331
1332 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301333 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001334 ss->transport = usb_stor_CB_transport;
1335 ss->transport_reset = usb_stor_CB_reset;
1336 break;
wdenkde887eb2003-09-10 18:20:28 +00001337 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301338 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001339 ss->transport = usb_stor_BBB_transport;
1340 ss->transport_reset = usb_stor_BBB_reset;
1341 break;
wdenkaffae2b2002-08-17 09:36:01 +00001342 default:
wdenk5f495752004-02-26 23:46:20 +00001343 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001344 return 0;
1345 break;
1346 }
1347
1348 /*
1349 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1350 * An optional interrupt is OK (necessary for CBI protocol).
1351 * We will ignore any others.
1352 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001353 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301354 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001355 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301356 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001357 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301358 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1359 ss->ep_in = ep_desc->bEndpointAddress &
1360 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001361 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001362 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301363 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001364 USB_ENDPOINT_NUMBER_MASK;
1365 }
1366
1367 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301368 if ((ep_desc->bmAttributes &
1369 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1370 ss->ep_int = ep_desc->bEndpointAddress &
1371 USB_ENDPOINT_NUMBER_MASK;
1372 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001373 }
1374 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301375 debug("Endpoints In %d Out %d Int %d\n",
1376 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001377
1378 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001379 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001380 !ss->ep_in || !ss->ep_out ||
1381 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301382 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001383 return 0;
1384 }
1385 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001386 /* We only handle certain protocols. Currently, these are
1387 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001388 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001389 */
wdenk5f495752004-02-26 23:46:20 +00001390 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1391 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001392 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001393 return 0;
1394 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001395 if (ss->ep_int) {
1396 /* we had found an interrupt endpoint, prepare irq pipe
1397 * set up the IRQ pipe and handler
1398 */
wdenkaffae2b2002-08-17 09:36:01 +00001399 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1400 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1401 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001402 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001403 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001404
1405 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001406 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001407
Michael Trimarchi956a4352008-12-10 15:52:06 +01001408 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001409 return 1;
1410}
1411
Michael Trimarchi956a4352008-12-10 15:52:06 +01001412int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001413 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001414{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001415 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001416 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1417 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1418 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001419 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001420
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001421 pccb->pdata = usb_stor_buf;
1422
1423 dev_desc->target = dev->devnum;
1424 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301425 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001426
Simon Glass78330d62015-03-25 12:22:12 -06001427 if (usb_inquiry(pccb, ss)) {
1428 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001429 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001430 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001431
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001432 perq = usb_stor_buf[0];
1433 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001434
Soeren Moche4828002014-11-08 07:02:14 +01001435 /*
1436 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1437 * they would not respond to test_unit_ready .
1438 */
1439 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001440 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001441 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001442 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001443 if ((modi&0x80) == 0x80) {
1444 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001445 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001446 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001447 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1448 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1449 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001450 dev_desc->vendor[8] = 0;
1451 dev_desc->product[16] = 0;
1452 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001453#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001454 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1455 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001456#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301457 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1458 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001459 if (usb_test_unit_ready(pccb, ss)) {
1460 printf("Device NOT ready\n"
1461 " Request Sense returned %02X %02X %02X\n",
1462 pccb->sense_buf[2], pccb->sense_buf[12],
1463 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001464 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001465 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001466 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001467 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001468 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001469 memset(pccb->pdata, 0, 8);
1470 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001471 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001472 cap[0] = 2880;
1473 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001474 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001475 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001476 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001477#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001478 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1479 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001480
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001481 cap[0] = cpu_to_be32(cap[0]);
1482 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001483#endif
1484
1485 capacity = be32_to_cpu(cap[0]) + 1;
1486 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001487
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001488 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1489 dev_desc->lba = capacity;
1490 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001491 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001492 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301493 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001494
wdenkaffae2b2002-08-17 09:36:01 +00001495 return 1;
1496}
Simon Glassac9774e2015-03-25 12:22:16 -06001497
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001498#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001499
1500static int usb_mass_storage_probe(struct udevice *dev)
1501{
Simon Glassde44acf2015-09-28 23:32:01 -06001502 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001503 int ret;
1504
1505 usb_disable_asynch(1); /* asynch transfer not allowed */
1506 ret = usb_stor_probe_device(udev);
1507 usb_disable_asynch(0); /* asynch transfer allowed */
1508
1509 return ret;
1510}
1511
1512static const struct udevice_id usb_mass_storage_ids[] = {
1513 { .compatible = "usb-mass-storage" },
1514 { }
1515};
1516
1517U_BOOT_DRIVER(usb_mass_storage) = {
1518 .name = "usb_mass_storage",
1519 .id = UCLASS_MASS_STORAGE,
1520 .of_match = usb_mass_storage_ids,
1521 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001522#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001523 .platdata_auto_alloc_size = sizeof(struct us_data),
1524#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001525};
1526
1527UCLASS_DRIVER(usb_mass_storage) = {
1528 .id = UCLASS_MASS_STORAGE,
1529 .name = "usb_mass_storage",
1530};
1531
1532static const struct usb_device_id mass_storage_id_table[] = {
1533 {
1534 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1535 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1536 },
1537 { } /* Terminating entry */
1538};
1539
Simon Glass46952fb2015-07-06 16:47:51 -06001540U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001541#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001542
Sven Schwermerc58ff202018-11-21 08:43:57 +01001543#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001544static const struct blk_ops usb_storage_ops = {
1545 .read = usb_stor_read,
1546 .write = usb_stor_write,
1547};
1548
1549U_BOOT_DRIVER(usb_storage_blk) = {
1550 .name = "usb_storage_blk",
1551 .id = UCLASS_BLK,
1552 .ops = &usb_storage_ops,
1553};
Simon Glassd3171412016-05-01 11:36:06 -06001554#else
1555U_BOOT_LEGACY_BLK(usb) = {
1556 .if_typename = "usb",
1557 .if_type = IF_TYPE_USB,
1558 .max_devs = USB_MAX_STOR_DEV,
1559 .desc = usb_dev_desc,
1560};
Simon Glassac9774e2015-03-25 12:22:16 -06001561#endif