blob: 76af7cc6bd40f5082df86adc3783d4305dfd0d7f [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>
Simon Glass274e0b02020-05-10 11:39:56 -060042#include <asm/cache.h>
wdenkaffae2b2002-08-17 09:36:01 +000043#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060044#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070045#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000046
Grant Likelyffc2dd72007-02-20 09:04:34 +010047#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000048#include <usb.h>
49
wdenk5f495752004-02-26 23:46:20 +000050#undef BBB_COMDAT_TRACE
51#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000052
wdenkaffae2b2002-08-17 09:36:01 +000053#include <scsi.h>
54/* direction table -- this indicates the direction of the data
55 * transfer for each command code -- a 1 indicates input
56 */
Mike Frysinger165522b2010-10-20 07:16:04 -040057static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000058 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
59 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
62};
63#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
64
Simon Glass5fb559d2017-06-14 21:28:30 -060065static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010066static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000067
Michael Trimarchi956a4352008-12-10 15:52:06 +010068static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000069
Sven Schwermerc58ff202018-11-21 08:43:57 +010070#if !CONFIG_IS_ENABLED(BLK)
Simon Glasse3394752016-02-29 15:25:34 -070071static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070072#endif
wdenkaffae2b2002-08-17 09:36:01 +000073
74struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060075typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010076typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000077
78struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010079 struct usb_device *pusb_dev; /* this usb_device */
80
81 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020082# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010083 unsigned char ifnum; /* interface number */
84 unsigned char ep_in; /* in endpoint */
85 unsigned char ep_out; /* out ....... */
86 unsigned char ep_int; /* interrupt . */
87 unsigned char subclass; /* as in overview */
88 unsigned char protocol; /* .............. */
89 unsigned char attention_done; /* force attn on first cmd */
90 unsigned short ip_data; /* interrupt data */
91 int action; /* what to do */
92 int ip_wanted; /* needed */
93 int *irq_handle; /* for USB int requests */
94 unsigned int irqpipe; /* pipe for release_irq */
95 unsigned char irqmaxp; /* max packed for irq Pipe */
96 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -060097 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +010098 trans_reset transport_reset; /* reset routine */
99 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -0700100 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000101};
102
Sven Schwermerc58ff202018-11-21 08:43:57 +0100103#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000104static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700105#endif
wdenkaffae2b2002-08-17 09:36:01 +0000106
wdenk5f495752004-02-26 23:46:20 +0000107#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000108#define USB_STOR_TRANSPORT_FAILED -1
109#define USB_STOR_TRANSPORT_ERROR -2
110
Michael Trimarchi956a4352008-12-10 15:52:06 +0100111int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700112 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100113int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
114 struct us_data *ss);
Sven Schwermerc58ff202018-11-21 08:43:57 +0100115#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700116static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
117 lbaint_t blkcnt, void *buffer);
118static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
119 lbaint_t blkcnt, const void *buffer);
120#else
Simon Glasse3394752016-02-29 15:25:34 -0700121static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700122 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700123static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700124 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700125#endif
wdenkaffae2b2002-08-17 09:36:01 +0000126void uhci_show_temp_int_td(void);
127
Kim Phillipsb052b602012-10-29 13:34:32 +0000128static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000129{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200130 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000131}
132
Michael Trimarchi956a4352008-12-10 15:52:06 +0100133/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200134 * show info on storage devices; 'usb start/init' must be invoked earlier
135 * as we only retrieve structures populated during devices initialization
136 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100137int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200138{
Simon Glass99e598e2016-02-29 15:25:54 -0700139 int count = 0;
Sven Schwermerc58ff202018-11-21 08:43:57 +0100140#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700141 struct udevice *dev;
142
143 for (blk_first_device(IF_TYPE_USB, &dev);
144 dev;
145 blk_next_device(&dev)) {
146 struct blk_desc *desc = dev_get_uclass_platdata(dev);
147
148 printf(" Device %d: ", desc->devnum);
149 dev_print(desc);
150 count++;
151 }
152#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200153 int i;
154
Aras Vaichas7ede1862008-03-25 12:09:07 +1100155 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200156 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100157 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200158 dev_print(&usb_dev_desc[i]);
159 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100160 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100161 }
Simon Glass01f5be92016-02-29 15:25:58 -0700162#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700163 if (!count) {
164 printf("No storage devices, perhaps not 'usb start'ed..?\n");
165 return 1;
166 }
167
Simon Glass8c6c0742016-03-16 07:45:44 -0600168 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200169}
170
Ludovic Courtès134396c2010-10-05 22:04:26 +0200171static unsigned int usb_get_max_lun(struct us_data *us)
172{
173 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530174 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200175 len = usb_control_msg(us->pusb_dev,
176 usb_rcvctrlpipe(us->pusb_dev, 0),
177 US_BBB_GET_MAX_LUN,
178 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
179 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530180 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200181 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530182 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530183 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200184}
185
Simon Glass99e598e2016-02-29 15:25:54 -0700186static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600187{
Simon Glass99e598e2016-02-29 15:25:54 -0700188 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700189
Sven Schwermerc58ff202018-11-21 08:43:57 +0100190#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700191 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700192 int ret;
193#else
Simon Glass99e598e2016-02-29 15:25:54 -0700194 int start;
195
196 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600197 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700198#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600199
Simon Glass01f5be92016-02-29 15:25:58 -0700200 debug("\n\nProbing for storage\n");
Sven Schwermerc58ff202018-11-21 08:43:57 +0100201#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -0700202 /*
203 * We store the us_data in the mass storage device's platdata. It
204 * is shared by all LUNs (block devices) attached to this mass storage
205 * device.
206 */
207 data = dev_get_platdata(udev->dev);
208 if (!usb_storage_probe(udev, 0, data))
209 return 0;
210 max_lun = usb_get_max_lun(data);
211 for (lun = 0; lun <= max_lun; lun++) {
212 struct blk_desc *blkdev;
213 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600214 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700215
Simon Glass966b6952016-05-01 11:36:29 -0600216 snprintf(str, sizeof(str), "lun%d", lun);
217 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
218 IF_TYPE_USB, usb_max_devs, 512, 0,
219 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700220 if (ret) {
221 debug("Cannot bind driver\n");
222 return ret;
223 }
224
225 blkdev = dev_get_uclass_platdata(dev);
226 blkdev->target = 0xff;
227 blkdev->lun = lun;
228
229 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengcbc3da82018-10-15 02:21:07 -0700230 if (ret == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700231 usb_max_devs++;
232 debug("%s: Found device %p\n", __func__, udev);
233 } else {
234 debug("usb_stor_get_info: Invalid device\n");
235 ret = device_unbind(dev);
236 if (ret)
237 return ret;
238 }
239 }
240#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700241 /* We don't have space to even probe if we hit the maximum */
242 if (usb_max_devs == USB_MAX_STOR_DEV) {
243 printf("max USB Storage Device reached: %d stopping\n",
244 usb_max_devs);
245 return -ENOSPC;
246 }
247
Simon Glass99e598e2016-02-29 15:25:54 -0700248 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
249 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600250
Simon Glass99e598e2016-02-29 15:25:54 -0700251 /*
252 * OK, it's a storage device. Iterate over its LUNs and populate
253 * usb_dev_desc'
254 */
255 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600256
Simon Glass99e598e2016-02-29 15:25:54 -0700257 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
258 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
259 lun++) {
260 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600261
Simon Glass99e598e2016-02-29 15:25:54 -0700262 blkdev = &usb_dev_desc[usb_max_devs];
263 memset(blkdev, '\0', sizeof(struct blk_desc));
264 blkdev->if_type = IF_TYPE_USB;
265 blkdev->devnum = usb_max_devs;
266 blkdev->part_type = PART_TYPE_UNKNOWN;
267 blkdev->target = 0xff;
268 blkdev->type = DEV_TYPE_UNKNOWN;
269 blkdev->block_read = usb_stor_read;
270 blkdev->block_write = usb_stor_write;
271 blkdev->lun = lun;
272 blkdev->priv = udev;
273
274 if (usb_stor_get_info(udev, &usb_stor[start],
275 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700276 debug("partype: %d\n", blkdev->part_type);
277 part_init(blkdev);
278 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700279 usb_max_devs++;
280 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600281 }
282 }
Simon Glass01f5be92016-02-29 15:25:58 -0700283#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600284
Simon Glassdf7d34f2015-03-25 12:22:15 -0600285 return 0;
286}
287
288void usb_stor_reset(void)
289{
290 usb_max_devs = 0;
291}
292
Michael Trimarchi956a4352008-12-10 15:52:06 +0100293/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200294 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000295 * to the user if mode = 1
296 * returns current device or -1 if no
297 */
298int usb_stor_scan(int mode)
299{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100300 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200301 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100302
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100303#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekcd8f86f2016-12-21 09:35:08 +0100304 unsigned char i;
305
wdenkaffae2b2002-08-17 09:36:01 +0000306 usb_disable_asynch(1); /* asynch transfer not allowed */
307
Simon Glassdf7d34f2015-03-25 12:22:15 -0600308 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100309 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600310 struct usb_device *dev;
311
Michael Trimarchi956a4352008-12-10 15:52:06 +0100312 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530313 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600314 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000315 break;
wdenkaffae2b2002-08-17 09:36:01 +0000316 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200317
wdenkaffae2b2002-08-17 09:36:01 +0000318 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100319#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200320 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100321 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000322 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100323 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000324}
325
326static int usb_stor_irq(struct usb_device *dev)
327{
328 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100329 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000330
Michael Trimarchi956a4352008-12-10 15:52:06 +0100331 if (us->ip_wanted)
332 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000333 return 0;
334}
335
336
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530337#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000338
Simon Glass5fb559d2017-06-14 21:28:30 -0600339static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000340{
341 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100342 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
343 for (i = 0; i < 12; i++)
344 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000345 printf("\n");
346}
347
348static void display_int_status(unsigned long tmp)
349{
350 printf("Status: %s %s %s %s %s %s %s\n",
351 (tmp & USB_ST_ACTIVE) ? "Active" : "",
352 (tmp & USB_ST_STALLED) ? "Stalled" : "",
353 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
354 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
355 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
356 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
357 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
358}
359#endif
360/***********************************************************************
361 * Data transfer routines
362 ***********************************************************************/
363
364static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
365{
366 int max_size;
367 int this_xfer;
368 int result;
369 int partial;
370 int maxtry;
371 int stat;
372
373 /* determine the maximum packet size for these transfers */
374 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
375
376 /* while we have data left to transfer */
377 while (length) {
378
379 /* calculate how long this will be -- maximum or a remainder */
380 this_xfer = length > max_size ? max_size : length;
381 length -= this_xfer;
382
383 /* setup the retry counter */
384 maxtry = 10;
385
386 /* set up the transfer loop */
387 do {
388 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600389 debug("Bulk xfer 0x%lx(%d) try #%d\n",
390 (ulong)map_to_sysmem(buf), this_xfer,
391 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000392 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100393 this_xfer, &partial,
394 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530395 debug("bulk_msg returned %d xferred %d/%d\n",
396 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100397 if (us->pusb_dev->status != 0) {
398 /* if we stall, we need to clear it before
399 * we go on
400 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530401#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000402 display_int_status(us->pusb_dev->status);
403#endif
404 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530405 debug("stalled ->clearing endpoint" \
406 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000407 stat = us->pusb_dev->status;
408 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100409 us->pusb_dev->status = stat;
410 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530411 debug("bulk transferred" \
412 "with error %lX," \
413 " but data ok\n",
414 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000415 return 0;
416 }
417 else
418 return result;
419 }
420 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530421 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000422 return result;
423 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530424 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100425 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530426 debug(" %ld, but data ok\n",
427 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000428 return 0;
429 }
430 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530431 debug(" %ld, data %d\n",
432 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000433 if (!maxtry--)
434 return result;
435 }
436 /* update to show what data was transferred */
437 this_xfer -= partial;
438 buf += partial;
439 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100440 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000441 }
442
443 /* if we get here, we're done and successful */
444 return 0;
445}
446
wdenkde887eb2003-09-10 18:20:28 +0000447static int usb_stor_BBB_reset(struct us_data *us)
448{
449 int result;
450 unsigned int pipe;
451
452 /*
453 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
454 *
455 * For Reset Recovery the host shall issue in the following order:
456 * a) a Bulk-Only Mass Storage Reset
457 * b) a Clear Feature HALT to the Bulk-In endpoint
458 * c) a Clear Feature HALT to the Bulk-Out endpoint
459 *
460 * This is done in 3 steps.
461 *
462 * If the reset doesn't succeed, the device should be port reset.
463 *
464 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
465 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530466 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100467 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
468 US_BBB_RESET,
469 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000470 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200471
Michael Trimarchi956a4352008-12-10 15:52:06 +0100472 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530473 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000474 return -1;
475 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200476
wdenkde887eb2003-09-10 18:20:28 +0000477 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000478 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530479 debug("BBB_reset result %d: status %lX reset\n",
480 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000481 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
482 result = usb_clear_halt(us->pusb_dev, pipe);
483 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000484 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530485 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
486 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000487 /* long wait for reset */
488 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
489 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000490 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530491 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
492 result, us->pusb_dev->status);
493 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000494 return 0;
495}
496
wdenkaffae2b2002-08-17 09:36:01 +0000497/* FIXME: this reset function doesn't really reset the port, and it
498 * should. Actually it should probably do what it's doing here, and
499 * reset the port physically
500 */
501static int usb_stor_CB_reset(struct us_data *us)
502{
503 unsigned char cmd[12];
504 int result;
505
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530506 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100507 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000508 cmd[0] = SCSI_SEND_DIAG;
509 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100510 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
511 US_CBI_ADSC,
512 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
513 0, us->ifnum, cmd, sizeof(cmd),
514 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000515
516 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000517 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530518 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
519 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000520 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
521 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
522
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530523 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000524 return 0;
525}
526
wdenkde887eb2003-09-10 18:20:28 +0000527/*
528 * Set up the command for a BBB device. Note that the actual SCSI
529 * command is copied into cbw.CBWCDB.
530 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600531static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000532{
533 int result;
534 int actlen;
535 int dir_in;
536 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600537 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000538
539 dir_in = US_DIRECTION(srb->cmd[0]);
540
541#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530542 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100543 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
544 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000545 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100546 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000547 printf("cmd[%d] %#x ", result, srb->cmd[result]);
548 printf("\n");
549 }
550#endif
551 /* sanity checks */
552 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530553 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000554 return -1;
555 }
556
557 /* always OUT to the ep */
558 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
559
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530560 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
561 cbw->dCBWTag = cpu_to_le32(CBWTag++);
562 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
563 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
564 cbw->bCBWLUN = srb->lun;
565 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000566 /* copy the command data into the CBW command data buffer */
567 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300568
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530569 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
570 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100571 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000572 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530573 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000574 return result;
575}
576
wdenkaffae2b2002-08-17 09:36:01 +0000577/* FIXME: we also need a CBI_command which sets up the completion
578 * interrupt, and waits for it
579 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600580static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000581{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200582 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100583 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000584 unsigned int pipe;
585 unsigned long status;
586
Michael Trimarchi956a4352008-12-10 15:52:06 +0100587 retry = 5;
588 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000589
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 if (dir_in)
591 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
592 else
593 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
594
595 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530596 debug("CBI gets a command: Try %d\n", 5 - retry);
597#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000598 usb_show_srb(srb);
599#endif
600 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100601 result = usb_control_msg(us->pusb_dev,
602 usb_sndctrlpipe(us->pusb_dev , 0),
603 US_CBI_ADSC,
604 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000605 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100606 srb->cmd, srb->cmdlen,
607 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530608 debug("CB_transport: control msg returned %d, status %lX\n",
609 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000610 /* check the return code for the command */
611 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100612 if (us->pusb_dev->status & USB_ST_STALLED) {
613 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530614 debug(" stall during command found," \
615 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100616 usb_clear_halt(us->pusb_dev,
617 usb_sndctrlpipe(us->pusb_dev, 0));
618 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000619 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530620 debug(" error during command %02X" \
621 " Stat = %lX\n", srb->cmd[0],
622 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000623 return result;
624 }
625 /* transfer the data payload for this command, if one exists*/
626
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530627 debug("CB_transport: control msg returned %d," \
628 " direction is %s to go 0x%lx\n", result,
629 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000630 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100631 result = us_one_transfer(us, pipe, (char *)srb->pdata,
632 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530633 debug("CBI attempted to transfer data," \
634 " result is %d status %lX, len %d\n",
635 result, us->pusb_dev->status,
636 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100637 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000638 break;
639 } /* if (srb->datalen) */
640 else
641 break;
642 }
643 /* return result */
644
645 return result;
646}
647
648
Simon Glass5fb559d2017-06-14 21:28:30 -0600649static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000650{
651 int timeout;
652
wdenk5f495752004-02-26 23:46:20 +0000653 us->ip_wanted = 1;
Michal Suchanek0089d212019-08-18 10:55:26 +0200654 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200655 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk5f495752004-02-26 23:46:20 +0000656 timeout = 1000;
657 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300658 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000659 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000660 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000661 }
662 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100663 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000664 us->ip_wanted = 0;
665 return USB_STOR_TRANSPORT_ERROR;
666 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700667 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530668 us->ip_data, us->pusb_dev->irq_act_len,
669 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000670 /* UFI gives us ASC and ASCQ, like a request sense */
671 if (us->subclass == US_SC_UFI) {
672 if (srb->cmd[0] == SCSI_REQ_SENSE ||
673 srb->cmd[0] == SCSI_INQUIRY)
674 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000675 else if (us->ip_data)
676 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000677 else
wdenk5f495752004-02-26 23:46:20 +0000678 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000679 }
680 /* otherwise, we interpret the data normally */
681 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000682 case 0x0001:
683 return USB_STOR_TRANSPORT_GOOD;
684 case 0x0002:
685 return USB_STOR_TRANSPORT_FAILED;
686 default:
687 return USB_STOR_TRANSPORT_ERROR;
688 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000689 return USB_STOR_TRANSPORT_ERROR;
690}
691
692#define USB_TRANSPORT_UNKNOWN_RETRY 5
693#define USB_TRANSPORT_NOT_READY_RETRY 10
694
wdenkde887eb2003-09-10 18:20:28 +0000695/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000696static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000697{
wdenkde887eb2003-09-10 18:20:28 +0000698 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900699 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
700 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
701 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000702}
703
Simon Glass5fb559d2017-06-14 21:28:30 -0600704static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000705{
706 int result, retry;
707 int dir_in;
708 int actlen, data_actlen;
709 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600710 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000711#ifdef BBB_XPORT_TRACE
712 unsigned char *ptr;
713 int index;
714#endif
715
716 dir_in = US_DIRECTION(srb->cmd[0]);
717
718 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530719 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000720 result = usb_stor_BBB_comdat(srb, us);
721 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530722 debug("failed to send CBW status %ld\n",
723 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000724 usb_stor_BBB_reset(us);
725 return USB_STOR_TRANSPORT_FAILED;
726 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200727 if (!(us->flags & USB_READY))
728 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000729 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
730 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
731 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000732 data_actlen = 0;
733 /* no data, go immediately to the STATUS phase */
734 if (srb->datalen == 0)
735 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530736 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000737 if (dir_in)
738 pipe = pipein;
739 else
740 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300741
Michael Trimarchi956a4352008-12-10 15:52:06 +0100742 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
743 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000744 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100745 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530746 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000747 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100748 result = usb_stor_BBB_clear_endpt_stall(us,
749 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000750 if (result >= 0)
751 /* continue on to STATUS phase */
752 goto st;
753 }
754 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530755 debug("usb_bulk_msg error status %ld\n",
756 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000757 usb_stor_BBB_reset(us);
758 return USB_STOR_TRANSPORT_FAILED;
759 }
760#ifdef BBB_XPORT_TRACE
761 for (index = 0; index < data_actlen; index++)
762 printf("pdata[%d] %#x ", index, srb->pdata[index]);
763 printf("\n");
764#endif
765 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100766st:
wdenkde887eb2003-09-10 18:20:28 +0000767 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100768again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530769 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530770 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200771 &actlen, USB_CNTL_TIMEOUT*5);
772
wdenkde887eb2003-09-10 18:20:28 +0000773 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100774 if ((result < 0) && (retry < 1) &&
775 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530776 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000777 /* clear the STALL on the endpoint */
778 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
779 if (result >= 0 && (retry++ < 1))
780 /* do a retry */
781 goto again;
782 }
783 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530784 debug("usb_bulk_msg error status %ld\n",
785 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000786 usb_stor_BBB_reset(us);
787 return USB_STOR_TRANSPORT_FAILED;
788 }
789#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530790 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000791 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
792 printf("ptr[%d] %#x ", index, ptr[index]);
793 printf("\n");
794#endif
795 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530796 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000797 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
798 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530799 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530800 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000801 usb_stor_BBB_reset(us);
802 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530803 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530804 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000805 usb_stor_BBB_reset(us);
806 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530807 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530808 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000809 usb_stor_BBB_reset(us);
810 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530811 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530812 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000813 usb_stor_BBB_reset(us);
814 return USB_STOR_TRANSPORT_FAILED;
815 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530816 debug("transferred %dB instead of %ldB\n",
817 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000818 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530819 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530820 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000821 return USB_STOR_TRANSPORT_FAILED;
822 }
823
824 return result;
825}
826
Simon Glass5fb559d2017-06-14 21:28:30 -0600827static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000828{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100829 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600830 struct scsi_cmd *psrb;
831 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100832 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000833
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200834 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100835 status = USB_STOR_TRANSPORT_GOOD;
836 retry = 0;
837 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000838 /* issue the command */
839do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100840 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530841 debug("command / Data returned %d, status %lX\n",
842 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000843 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100844 if (us->protocol == US_PR_CBI) {
845 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000846 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530848 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000849 return status;
850 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100851 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
852 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
853 if (!us->ip_data) {
854 /* if the status is good, report it */
855 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530856 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000857 return status;
858 }
859 }
860 }
861 /* do we have to issue an auto request? */
862 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100863 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530864 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000865 us->transport_reset(us);
866 return USB_STOR_TRANSPORT_ERROR;
867 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100868 if ((us->protocol == US_PR_CBI) &&
869 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
870 (srb->cmd[0] == SCSI_INQUIRY))) {
871 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530872 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000873 return USB_STOR_TRANSPORT_GOOD;
874 }
875 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100876 memset(&psrb->cmd[0], 0, 12);
877 psrb->cmd[0] = SCSI_REQ_SENSE;
878 psrb->cmd[1] = srb->lun << 5;
879 psrb->cmd[4] = 18;
880 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200881 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100882 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000883 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100884 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530885 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000886 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100887 if (us->protocol == US_PR_CBI)
888 status = usb_stor_CBI_get_status(psrb, us);
889
890 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530891 debug(" AUTO REQUEST ERROR %ld\n",
892 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000893 return USB_STOR_TRANSPORT_ERROR;
894 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530895 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
896 srb->sense_buf[0], srb->sense_buf[2],
897 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000898 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100899 if ((srb->sense_buf[2] == 0) &&
900 (srb->sense_buf[12] == 0) &&
901 (srb->sense_buf[13] == 0)) {
902 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000903 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100904 }
905
wdenkaffae2b2002-08-17 09:36:01 +0000906 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100907 switch (srb->sense_buf[2]) {
908 case 0x01:
909 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000910 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000911 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100912 case 0x02:
913 /* Not Ready */
914 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
915 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
916 " 0x%02X (NOT READY)\n", srb->cmd[0],
917 srb->sense_buf[0], srb->sense_buf[2],
918 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000919 return USB_STOR_TRANSPORT_FAILED;
920 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000921 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000922 goto do_retry;
923 }
924 break;
925 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100926 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
927 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
928 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
929 srb->sense_buf[2], srb->sense_buf[12],
930 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000931 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100932 } else
wdenkde887eb2003-09-10 18:20:28 +0000933 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000934 break;
wdenkaffae2b2002-08-17 09:36:01 +0000935 }
936 return USB_STOR_TRANSPORT_FAILED;
937}
938
Bin Meng9f447112017-09-07 06:13:21 -0700939static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
940 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700941{
Bin Mengf6e373e2017-09-07 06:13:20 -0700942 /*
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200943 * Limit the total size of a transfer to 120 KB.
944 *
945 * Some devices are known to choke with anything larger. It seems like
946 * the problem stems from the fact that original IDE controllers had
947 * only an 8-bit register to hold the number of sectors in one transfer
948 * and even those couldn't handle a full 256 sectors.
949 *
950 * Because we want to make sure we interoperate with as many devices as
951 * possible, we will maintain a 240 sector transfer size limit for USB
952 * Mass Storage devices.
953 *
954 * Tests show that other operating have similar limits with Microsoft
955 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
956 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
957 * and 2048 for USB3 devices.
Bin Mengf6e373e2017-09-07 06:13:20 -0700958 */
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200959 unsigned short blk = 240;
960
961#if CONFIG_IS_ENABLED(DM_USB)
962 size_t size;
963 int ret;
964
Bin Meng9f447112017-09-07 06:13:21 -0700965 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasutcc93ffd2019-09-16 00:16:25 +0200966 if ((ret >= 0) && (size < blk * 512))
Bin Meng9f447112017-09-07 06:13:21 -0700967 blk = size / 512;
Bin Meng9f447112017-09-07 06:13:21 -0700968#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700969
970 us->max_xfer_blk = blk;
971}
wdenkaffae2b2002-08-17 09:36:01 +0000972
Simon Glass5fb559d2017-06-14 21:28:30 -0600973static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000974{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100975 int retry, i;
976 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000977 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978 memset(&srb->cmd[0], 0, 12);
979 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200980 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 srb->cmd[4] = 36;
982 srb->datalen = 36;
983 srb->cmdlen = 12;
984 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530985 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100986 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000987 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200988 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000989
Michael Trimarchi956a4352008-12-10 15:52:06 +0100990 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000991 printf("error in inquiry\n");
992 return -1;
993 }
994 return 0;
995}
996
Simon Glass5fb559d2017-06-14 21:28:30 -0600997static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000998{
999 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001000
Michael Trimarchi956a4352008-12-10 15:52:06 +01001001 ptr = (char *)srb->pdata;
1002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001005 srb->cmd[4] = 18;
1006 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001007 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 srb->cmdlen = 12;
1009 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301010 debug("Request Sense returned %02X %02X %02X\n",
1011 srb->sense_buf[2], srb->sense_buf[12],
1012 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001013 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001014 return 0;
1015}
1016
Simon Glass5fb559d2017-06-14 21:28:30 -06001017static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001018{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001019 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001020
wdenkaffae2b2002-08-17 09:36:01 +00001021 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001022 memset(&srb->cmd[0], 0, 12);
1023 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001024 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001025 srb->datalen = 0;
1026 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001027 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1028 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001029 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001030 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001032 /*
1033 * Check the Key Code Qualifier, if it matches
1034 * "Not Ready - medium not present"
1035 * (the sense Key equals 0x2 and the ASC is 0x3a)
1036 * return immediately as the medium being absent won't change
1037 * unless there is a user action.
1038 */
1039 if ((srb->sense_buf[2] == 0x02) &&
1040 (srb->sense_buf[12] == 0x3a))
1041 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001042 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001043 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001044
wdenkaffae2b2002-08-17 09:36:01 +00001045 return -1;
1046}
1047
Simon Glass5fb559d2017-06-14 21:28:30 -06001048static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001049{
1050 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001051 /* XXX retries */
1052 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001053 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001054 memset(&srb->cmd[0], 0, 12);
1055 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001056 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001057 srb->datalen = 8;
1058 srb->cmdlen = 12;
1059 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001060 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001061 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001062
wdenkaffae2b2002-08-17 09:36:01 +00001063 return -1;
1064}
1065
Simon Glass5fb559d2017-06-14 21:28:30 -06001066static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1067 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001068{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 memset(&srb->cmd[0], 0, 12);
1070 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001071 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1073 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1074 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1075 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1076 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1077 srb->cmd[8] = (unsigned char) blocks & 0xff;
1078 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301079 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001081}
1082
Simon Glass5fb559d2017-06-14 21:28:30 -06001083static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1084 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301085{
1086 memset(&srb->cmd[0], 0, 12);
1087 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001088 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301089 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1090 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1091 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1092 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1093 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1094 srb->cmd[8] = (unsigned char) blocks & 0xff;
1095 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301096 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301097 return ss->transport(srb, ss);
1098}
1099
wdenkaffae2b2002-08-17 09:36:01 +00001100
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001101#ifdef CONFIG_USB_BIN_FIXUP
1102/*
1103 * Some USB storage devices queried for SCSI identification data respond with
1104 * binary strings, which if output to the console freeze the terminal. The
1105 * workaround is to modify the vendor and product strings read from such
1106 * device with proper values (as reported by 'usb info').
1107 *
1108 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001109 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001110 */
1111static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1112 unsigned char vendor[],
1113 unsigned char product[]) {
1114 const unsigned char max_vendor_len = 40;
1115 const unsigned char max_product_len = 20;
1116 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001117 strncpy((char *)vendor, "SMSC", max_vendor_len);
1118 strncpy((char *)product, "Flash Media Cntrller",
1119 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001120 }
1121}
1122#endif /* CONFIG_USB_BIN_FIXUP */
1123
Sven Schwermerc58ff202018-11-21 08:43:57 +01001124#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001125static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1126 lbaint_t blkcnt, void *buffer)
1127#else
Simon Glasse3394752016-02-29 15:25:34 -07001128static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001129 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001130#endif
wdenkaffae2b2002-08-17 09:36:01 +00001131{
Gabe Black7d077682012-10-12 14:26:07 +00001132 lbaint_t start, blks;
1133 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001134 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001135 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001136 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001137 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001138 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001139#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001140 struct blk_desc *block_dev;
1141#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001142
1143 if (blkcnt == 0)
1144 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001145 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001146#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001147 block_dev = dev_get_uclass_platdata(dev);
1148 udev = dev_get_parent_priv(dev_get_parent(dev));
1149 debug("\nusb_read: udev %d\n", block_dev->devnum);
1150#else
Simon Glass99e598e2016-02-29 15:25:54 -07001151 debug("\nusb_read: udev %d\n", block_dev->devnum);
1152 udev = usb_dev_desc[block_dev->devnum].priv;
1153 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001154 debug("%s: No device\n", __func__);
1155 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001156 }
Simon Glass01f5be92016-02-29 15:25:58 -07001157#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001158 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001159
1160 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001161 usb_lock_async(udev, 1);
Simon Glass99e598e2016-02-29 15:25:54 -07001162 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001163 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001164 start = blknr;
1165 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001166
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001167 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1168 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001169
wdenkaffae2b2002-08-17 09:36:01 +00001170 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001171 /* XXX need some comment here */
1172 retry = 2;
1173 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001174 if (blks > ss->max_xfer_blk)
1175 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001176 else
1177 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001178retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001179 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001180 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001181 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001182 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001183 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301184 debug("Read ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001185 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001186 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001187 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001188 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001189 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001190 break;
1191 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001192 start += smallblks;
1193 blks -= smallblks;
1194 buf_addr += srb->datalen;
1195 } while (blks != 0);
1196
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001197 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301198 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001199
Marek Vasut118a9032020-04-06 14:29:44 +02001200 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001201 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001202 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001203 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001204 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001205}
1206
Sven Schwermerc58ff202018-11-21 08:43:57 +01001207#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001208static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1209 lbaint_t blkcnt, const void *buffer)
1210#else
Simon Glasse3394752016-02-29 15:25:34 -07001211static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001212 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001213#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301214{
Gabe Black7d077682012-10-12 14:26:07 +00001215 lbaint_t start, blks;
1216 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301217 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001218 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001219 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001220 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001221 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermerc58ff202018-11-21 08:43:57 +01001222#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001223 struct blk_desc *block_dev;
1224#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301225
1226 if (blkcnt == 0)
1227 return 0;
1228
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301229 /* Setup device */
Sven Schwermerc58ff202018-11-21 08:43:57 +01001230#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001231 block_dev = dev_get_uclass_platdata(dev);
1232 udev = dev_get_parent_priv(dev_get_parent(dev));
1233 debug("\nusb_read: udev %d\n", block_dev->devnum);
1234#else
Simon Glass99e598e2016-02-29 15:25:54 -07001235 debug("\nusb_read: udev %d\n", block_dev->devnum);
1236 udev = usb_dev_desc[block_dev->devnum].priv;
1237 if (!udev) {
1238 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001239 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001240 }
Simon Glass01f5be92016-02-29 15:25:58 -07001241#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001242 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301243
1244 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut118a9032020-04-06 14:29:44 +02001245 usb_lock_async(udev, 1);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301246
Simon Glass99e598e2016-02-29 15:25:54 -07001247 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001248 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301249 start = blknr;
1250 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301251
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001252 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1253 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301254
1255 do {
1256 /* If write fails retry for max retry count else
1257 * return with number of blocks written successfully.
1258 */
1259 retry = 2;
1260 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001261 if (blks > ss->max_xfer_blk)
1262 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301263 else
1264 smallblks = (unsigned short) blks;
1265retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001266 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301267 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001268 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301269 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001270 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301271 debug("Write ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001272 ss->flags &= ~USB_READY;
Kyle Moffett6540db02011-12-21 07:08:12 +00001273 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301274 if (retry--)
1275 goto retry_it;
1276 blkcnt -= blks;
1277 break;
1278 }
1279 start += smallblks;
1280 blks -= smallblks;
1281 buf_addr += srb->datalen;
1282 } while (blks != 0);
1283
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001284 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1285 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301286
Marek Vasut118a9032020-04-06 14:29:44 +02001287 usb_lock_async(udev, 0);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301288 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001289 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001290 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301291 return blkcnt;
1292
1293}
wdenkaffae2b2002-08-17 09:36:01 +00001294
1295/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001296int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1297 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001298{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001299 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001300 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301301 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001302 unsigned int flags = 0;
1303
wdenkaffae2b2002-08-17 09:36:01 +00001304 /* let's examine the device now */
1305 iface = &dev->config.if_desc[ifnum];
1306
wdenkaffae2b2002-08-17 09:36:01 +00001307 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001308 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1309 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1310 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001311 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001312 /* if it's not a mass storage, we go no further */
1313 return 0;
1314 }
1315
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001316 memset(ss, 0, sizeof(struct us_data));
1317
wdenkaffae2b2002-08-17 09:36:01 +00001318 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301319 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001320
1321 /* Initialize the us_data structure with some useful info */
1322 ss->flags = flags;
1323 ss->ifnum = ifnum;
1324 ss->pusb_dev = dev;
1325 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001326 ss->subclass = iface->desc.bInterfaceSubClass;
1327 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001328
1329 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301330 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001331 switch (ss->protocol) {
1332 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301333 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001334 ss->transport = usb_stor_CB_transport;
1335 ss->transport_reset = usb_stor_CB_reset;
1336 break;
1337
1338 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301339 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001340 ss->transport = usb_stor_CB_transport;
1341 ss->transport_reset = usb_stor_CB_reset;
1342 break;
wdenkde887eb2003-09-10 18:20:28 +00001343 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301344 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001345 ss->transport = usb_stor_BBB_transport;
1346 ss->transport_reset = usb_stor_BBB_reset;
1347 break;
wdenkaffae2b2002-08-17 09:36:01 +00001348 default:
wdenk5f495752004-02-26 23:46:20 +00001349 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001350 return 0;
1351 break;
1352 }
1353
1354 /*
1355 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1356 * An optional interrupt is OK (necessary for CBI protocol).
1357 * We will ignore any others.
1358 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001359 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301360 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001361 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301362 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001363 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301364 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1365 ss->ep_in = ep_desc->bEndpointAddress &
1366 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001367 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001368 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301369 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001370 USB_ENDPOINT_NUMBER_MASK;
1371 }
1372
1373 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301374 if ((ep_desc->bmAttributes &
1375 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1376 ss->ep_int = ep_desc->bEndpointAddress &
1377 USB_ENDPOINT_NUMBER_MASK;
1378 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001379 }
1380 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301381 debug("Endpoints In %d Out %d Int %d\n",
1382 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001383
1384 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001385 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001386 !ss->ep_in || !ss->ep_out ||
1387 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301388 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001389 return 0;
1390 }
1391 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001392 /* We only handle certain protocols. Currently, these are
1393 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001394 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001395 */
wdenk5f495752004-02-26 23:46:20 +00001396 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1397 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001398 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001399 return 0;
1400 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001401 if (ss->ep_int) {
1402 /* we had found an interrupt endpoint, prepare irq pipe
1403 * set up the IRQ pipe and handler
1404 */
wdenkaffae2b2002-08-17 09:36:01 +00001405 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1406 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1407 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001408 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001409 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001410
1411 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001412 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001413
Michael Trimarchi956a4352008-12-10 15:52:06 +01001414 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001415 return 1;
1416}
1417
Michael Trimarchi956a4352008-12-10 15:52:06 +01001418int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001419 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001420{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001421 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001422 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1423 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1424 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001425 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001426
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001427 pccb->pdata = usb_stor_buf;
1428
1429 dev_desc->target = dev->devnum;
1430 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301431 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001432
Simon Glass78330d62015-03-25 12:22:12 -06001433 if (usb_inquiry(pccb, ss)) {
1434 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001435 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001436 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001437
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001438 perq = usb_stor_buf[0];
1439 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001440
Soeren Moche4828002014-11-08 07:02:14 +01001441 /*
1442 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1443 * they would not respond to test_unit_ready .
1444 */
1445 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001446 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001447 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001449 if ((modi&0x80) == 0x80) {
1450 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001451 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001452 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001453 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1454 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1455 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001456 dev_desc->vendor[8] = 0;
1457 dev_desc->product[16] = 0;
1458 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001459#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001460 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1461 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001462#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301463 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1464 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001465 if (usb_test_unit_ready(pccb, ss)) {
1466 printf("Device NOT ready\n"
1467 " Request Sense returned %02X %02X %02X\n",
1468 pccb->sense_buf[2], pccb->sense_buf[12],
1469 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001470 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001471 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001472 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001473 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001474 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001475 memset(pccb->pdata, 0, 8);
1476 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001477 printf("READ_CAP ERROR\n");
Marek Vasut765e91a2019-10-05 19:18:38 +02001478 ss->flags &= ~USB_READY;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001479 cap[0] = 2880;
1480 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001481 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001482 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001483#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001484 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1485 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001486
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001487 cap[0] = cpu_to_be32(cap[0]);
1488 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001489#endif
1490
1491 capacity = be32_to_cpu(cap[0]) + 1;
1492 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001493
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001494 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1495 dev_desc->lba = capacity;
1496 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001497 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001498 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301499 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001500
wdenkaffae2b2002-08-17 09:36:01 +00001501 return 1;
1502}
Simon Glassac9774e2015-03-25 12:22:16 -06001503
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +01001504#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassac9774e2015-03-25 12:22:16 -06001505
1506static int usb_mass_storage_probe(struct udevice *dev)
1507{
Simon Glassde44acf2015-09-28 23:32:01 -06001508 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001509 int ret;
1510
1511 usb_disable_asynch(1); /* asynch transfer not allowed */
1512 ret = usb_stor_probe_device(udev);
1513 usb_disable_asynch(0); /* asynch transfer allowed */
1514
1515 return ret;
1516}
1517
1518static const struct udevice_id usb_mass_storage_ids[] = {
1519 { .compatible = "usb-mass-storage" },
1520 { }
1521};
1522
1523U_BOOT_DRIVER(usb_mass_storage) = {
1524 .name = "usb_mass_storage",
1525 .id = UCLASS_MASS_STORAGE,
1526 .of_match = usb_mass_storage_ids,
1527 .probe = usb_mass_storage_probe,
Sven Schwermerc58ff202018-11-21 08:43:57 +01001528#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001529 .platdata_auto_alloc_size = sizeof(struct us_data),
1530#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001531};
1532
1533UCLASS_DRIVER(usb_mass_storage) = {
1534 .id = UCLASS_MASS_STORAGE,
1535 .name = "usb_mass_storage",
1536};
1537
1538static const struct usb_device_id mass_storage_id_table[] = {
1539 {
1540 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1541 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1542 },
1543 { } /* Terminating entry */
1544};
1545
Simon Glass46952fb2015-07-06 16:47:51 -06001546U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001547#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001548
Sven Schwermerc58ff202018-11-21 08:43:57 +01001549#if CONFIG_IS_ENABLED(BLK)
Simon Glass01f5be92016-02-29 15:25:58 -07001550static const struct blk_ops usb_storage_ops = {
1551 .read = usb_stor_read,
1552 .write = usb_stor_write,
1553};
1554
1555U_BOOT_DRIVER(usb_storage_blk) = {
1556 .name = "usb_storage_blk",
1557 .id = UCLASS_BLK,
1558 .ops = &usb_storage_ops,
1559};
Simon Glassd3171412016-05-01 11:36:06 -06001560#else
1561U_BOOT_LEGACY_BLK(usb) = {
1562 .if_typename = "usb",
1563 .if_type = IF_TYPE_USB,
1564 .max_devs = USB_MAX_STOR_DEV,
1565 .desc = usb_dev_desc,
1566};
Simon Glassac9774e2015-03-25 12:22:16 -06001567#endif