blob: aba9ccb7f5b7bfd58062a6726cfd334d835ea12a [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00002/*
Wolfgang Denk460c3222005-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 Glassacf277a2015-03-25 12:22:16 -060013 * Driver model conversion:
14 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000015 *
wdenk149dded2003-09-10 18:20:28 +000016 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020017 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000018 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020019 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-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 */
wdenk149dded2003-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.
wdenk149dded2003-09-10 18:20:28 +000032 */
wdenkaffae2b2002-08-17 09:36:01 +000033
34
wdenkaffae2b2002-08-17 09:36:01 +000035#include <common.h>
Simon Glasse6f6f9e2020-05-10 11:39:58 -060036#include <blk.h>
wdenkaffae2b2002-08-17 09:36:01 +000037#include <command.h>
Simon Glassacf277a2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glass91557572015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass05108132015-03-25 12:22:14 -060040#include <mapmem.h>
Simon Glasscf92e052015-09-02 17:24:58 -060041#include <memalign.h>
Christian Eggersc9182612008-05-21 22:12:00 +020042#include <asm/byteorder.h>
Simon Glass90526e92020-05-10 11:39:56 -060043#include <asm/cache.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
Simon Glass07b2b782016-02-29 15:25:58 -070046#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000047
Grant Likely735dd972007-02-20 09:04:34 +010048#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000049#include <usb.h>
50
wdenk80885a92004-02-26 23:46:20 +000051#undef BBB_COMDAT_TRACE
52#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000053
wdenkaffae2b2002-08-17 09:36:01 +000054#include <scsi.h>
55/* direction table -- this indicates the direction of the data
56 * transfer for each command code -- a 1 indicates input
57 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040058static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000059 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
60 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
63};
64#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
65
Simon Glassb9560ad2017-06-14 21:28:30 -060066static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010067static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000068
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
Sven Schwermer1af9bfd2018-11-21 08:43:57 +010071#if !CONFIG_IS_ENABLED(BLK)
Simon Glass4101f682016-02-29 15:25:34 -070072static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -070073#endif
wdenkaffae2b2002-08-17 09:36:01 +000074
75struct us_data;
Simon Glassb9560ad2017-06-14 21:28:30 -060076typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010077typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000078
79struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010080 struct usb_device *pusb_dev; /* this usb_device */
81
82 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020083# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010084 unsigned char ifnum; /* interface number */
85 unsigned char ep_in; /* in endpoint */
86 unsigned char ep_out; /* out ....... */
87 unsigned char ep_int; /* interrupt . */
88 unsigned char subclass; /* as in overview */
89 unsigned char protocol; /* .............. */
90 unsigned char attention_done; /* force attn on first cmd */
91 unsigned short ip_data; /* interrupt data */
92 int action; /* what to do */
93 int ip_wanted; /* needed */
94 int *irq_handle; /* for USB int requests */
95 unsigned int irqpipe; /* pipe for release_irq */
96 unsigned char irqmaxp; /* max packed for irq Pipe */
97 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glassb9560ad2017-06-14 21:28:30 -060098 struct scsi_cmd *srb; /* current srb */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010099 trans_reset transport_reset; /* reset routine */
100 trans_cmnd transport; /* transport routine */
Bin Meng6158d0b2017-09-07 06:13:20 -0700101 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000102};
103
Sven Schwermer1af9bfd2018-11-21 08:43:57 +0100104#if !CONFIG_IS_ENABLED(BLK)
wdenkaffae2b2002-08-17 09:36:01 +0000105static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -0700106#endif
wdenkaffae2b2002-08-17 09:36:01 +0000107
wdenk80885a92004-02-26 23:46:20 +0000108#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000109#define USB_STOR_TRANSPORT_FAILED -1
110#define USB_STOR_TRANSPORT_ERROR -2
111
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100112int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glass4101f682016-02-29 15:25:34 -0700113 struct blk_desc *dev_desc);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100114int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
115 struct us_data *ss);
Sven Schwermer1af9bfd2018-11-21 08:43:57 +0100116#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -0700117static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
118 lbaint_t blkcnt, void *buffer);
119static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
120 lbaint_t blkcnt, const void *buffer);
121#else
Simon Glass4101f682016-02-29 15:25:34 -0700122static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700123 lbaint_t blkcnt, void *buffer);
Simon Glass4101f682016-02-29 15:25:34 -0700124static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700125 lbaint_t blkcnt, const void *buffer);
Simon Glass07b2b782016-02-29 15:25:58 -0700126#endif
wdenkaffae2b2002-08-17 09:36:01 +0000127void uhci_show_temp_int_td(void);
128
Kim Phillips199adb62012-10-29 13:34:32 +0000129static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000130{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200131 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000132}
133
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100134/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200135 * show info on storage devices; 'usb start/init' must be invoked earlier
136 * as we only retrieve structures populated during devices initialization
137 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100138int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200139{
Simon Glass9807c3b2016-02-29 15:25:54 -0700140 int count = 0;
Sven Schwermer1af9bfd2018-11-21 08:43:57 +0100141#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -0700142 struct udevice *dev;
143
144 for (blk_first_device(IF_TYPE_USB, &dev);
145 dev;
146 blk_next_device(&dev)) {
147 struct blk_desc *desc = dev_get_uclass_platdata(dev);
148
149 printf(" Device %d: ", desc->devnum);
150 dev_print(desc);
151 count++;
152 }
153#else
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200154 int i;
155
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100156 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200157 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100158 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200159 dev_print(&usb_dev_desc[i]);
160 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100161 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100162 }
Simon Glass07b2b782016-02-29 15:25:58 -0700163#endif
Simon Glass9807c3b2016-02-29 15:25:54 -0700164 if (!count) {
165 printf("No storage devices, perhaps not 'usb start'ed..?\n");
166 return 1;
167 }
168
Simon Glassb94fc852016-03-16 07:45:44 -0600169 return 0;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200170}
171
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200172static unsigned int usb_get_max_lun(struct us_data *us)
173{
174 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530175 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200176 len = usb_control_msg(us->pusb_dev,
177 usb_rcvctrlpipe(us->pusb_dev, 0),
178 US_BBB_GET_MAX_LUN,
179 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
180 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530181 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200182 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530183 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530184 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200185}
186
Simon Glass9807c3b2016-02-29 15:25:54 -0700187static int usb_stor_probe_device(struct usb_device *udev)
Simon Glass91557572015-03-25 12:22:15 -0600188{
Simon Glass9807c3b2016-02-29 15:25:54 -0700189 int lun, max_lun;
Simon Glass07b2b782016-02-29 15:25:58 -0700190
Sven Schwermer1af9bfd2018-11-21 08:43:57 +0100191#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -0700192 struct us_data *data;
Simon Glass07b2b782016-02-29 15:25:58 -0700193 int ret;
194#else
Simon Glass9807c3b2016-02-29 15:25:54 -0700195 int start;
196
197 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600198 return -ENOENT; /* no more devices available */
Simon Glass07b2b782016-02-29 15:25:58 -0700199#endif
Simon Glass91557572015-03-25 12:22:15 -0600200
Simon Glass07b2b782016-02-29 15:25:58 -0700201 debug("\n\nProbing for storage\n");
Sven Schwermer1af9bfd2018-11-21 08:43:57 +0100202#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -0700203 /*
204 * We store the us_data in the mass storage device's platdata. It
205 * is shared by all LUNs (block devices) attached to this mass storage
206 * device.
207 */
208 data = dev_get_platdata(udev->dev);
209 if (!usb_storage_probe(udev, 0, data))
210 return 0;
211 max_lun = usb_get_max_lun(data);
212 for (lun = 0; lun <= max_lun; lun++) {
213 struct blk_desc *blkdev;
214 struct udevice *dev;
Simon Glass9107c972016-05-01 11:36:29 -0600215 char str[10];
Simon Glass07b2b782016-02-29 15:25:58 -0700216
Simon Glass9107c972016-05-01 11:36:29 -0600217 snprintf(str, sizeof(str), "lun%d", lun);
218 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
219 IF_TYPE_USB, usb_max_devs, 512, 0,
220 &dev);
Simon Glass07b2b782016-02-29 15:25:58 -0700221 if (ret) {
222 debug("Cannot bind driver\n");
223 return ret;
224 }
225
226 blkdev = dev_get_uclass_platdata(dev);
227 blkdev->target = 0xff;
228 blkdev->lun = lun;
229
230 ret = usb_stor_get_info(udev, data, blkdev);
Bin Mengd0851c82018-10-15 02:21:07 -0700231 if (ret == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700232 usb_max_devs++;
233 debug("%s: Found device %p\n", __func__, udev);
234 } else {
235 debug("usb_stor_get_info: Invalid device\n");
236 ret = device_unbind(dev);
237 if (ret)
238 return ret;
239 }
240 }
241#else
Simon Glassc89e79d2016-02-29 15:25:53 -0700242 /* We don't have space to even probe if we hit the maximum */
243 if (usb_max_devs == USB_MAX_STOR_DEV) {
244 printf("max USB Storage Device reached: %d stopping\n",
245 usb_max_devs);
246 return -ENOSPC;
247 }
248
Simon Glass9807c3b2016-02-29 15:25:54 -0700249 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
250 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600251
Simon Glass9807c3b2016-02-29 15:25:54 -0700252 /*
253 * OK, it's a storage device. Iterate over its LUNs and populate
254 * usb_dev_desc'
255 */
256 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600257
Simon Glass9807c3b2016-02-29 15:25:54 -0700258 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
259 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
260 lun++) {
261 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600262
Simon Glass9807c3b2016-02-29 15:25:54 -0700263 blkdev = &usb_dev_desc[usb_max_devs];
264 memset(blkdev, '\0', sizeof(struct blk_desc));
265 blkdev->if_type = IF_TYPE_USB;
266 blkdev->devnum = usb_max_devs;
267 blkdev->part_type = PART_TYPE_UNKNOWN;
268 blkdev->target = 0xff;
269 blkdev->type = DEV_TYPE_UNKNOWN;
270 blkdev->block_read = usb_stor_read;
271 blkdev->block_write = usb_stor_write;
272 blkdev->lun = lun;
273 blkdev->priv = udev;
274
275 if (usb_stor_get_info(udev, &usb_stor[start],
276 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700277 debug("partype: %d\n", blkdev->part_type);
278 part_init(blkdev);
279 debug("partype: %d\n", blkdev->part_type);
Simon Glass9807c3b2016-02-29 15:25:54 -0700280 usb_max_devs++;
281 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600282 }
283 }
Simon Glass07b2b782016-02-29 15:25:58 -0700284#endif
Simon Glass91557572015-03-25 12:22:15 -0600285
Simon Glass91557572015-03-25 12:22:15 -0600286 return 0;
287}
288
289void usb_stor_reset(void)
290{
291 usb_max_devs = 0;
292}
293
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100294/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200295 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000296 * to the user if mode = 1
297 * returns current device or -1 if no
298 */
299int usb_stor_scan(int mode)
300{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100301 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200302 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100303
Sven Schwermerfd09c202018-11-21 08:43:56 +0100304#if !CONFIG_IS_ENABLED(DM_USB)
Michal Simekb9847002016-12-21 09:35:08 +0100305 unsigned char i;
306
wdenkaffae2b2002-08-17 09:36:01 +0000307 usb_disable_asynch(1); /* asynch transfer not allowed */
308
Simon Glass91557572015-03-25 12:22:15 -0600309 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100310 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600311 struct usb_device *dev;
312
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100313 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530314 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600315 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000316 break;
wdenkaffae2b2002-08-17 09:36:01 +0000317 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200318
wdenkaffae2b2002-08-17 09:36:01 +0000319 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekb9847002016-12-21 09:35:08 +0100320#endif
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200321 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100322 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000323 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100324 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000325}
326
327static int usb_stor_irq(struct usb_device *dev)
328{
329 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100330 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000331
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100332 if (us->ip_wanted)
333 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
335}
336
337
Vivek Gautamceb49722013-04-12 16:34:33 +0530338#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000339
Simon Glassb9560ad2017-06-14 21:28:30 -0600340static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000341{
342 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100343 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
344 for (i = 0; i < 12; i++)
345 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000346 printf("\n");
347}
348
349static void display_int_status(unsigned long tmp)
350{
351 printf("Status: %s %s %s %s %s %s %s\n",
352 (tmp & USB_ST_ACTIVE) ? "Active" : "",
353 (tmp & USB_ST_STALLED) ? "Stalled" : "",
354 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
355 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
356 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
357 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
358 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
359}
360#endif
361/***********************************************************************
362 * Data transfer routines
363 ***********************************************************************/
364
365static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
366{
367 int max_size;
368 int this_xfer;
369 int result;
370 int partial;
371 int maxtry;
372 int stat;
373
374 /* determine the maximum packet size for these transfers */
375 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
376
377 /* while we have data left to transfer */
378 while (length) {
379
380 /* calculate how long this will be -- maximum or a remainder */
381 this_xfer = length > max_size ? max_size : length;
382 length -= this_xfer;
383
384 /* setup the retry counter */
385 maxtry = 10;
386
387 /* set up the transfer loop */
388 do {
389 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600390 debug("Bulk xfer 0x%lx(%d) try #%d\n",
391 (ulong)map_to_sysmem(buf), this_xfer,
392 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000393 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100394 this_xfer, &partial,
395 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530396 debug("bulk_msg returned %d xferred %d/%d\n",
397 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100398 if (us->pusb_dev->status != 0) {
399 /* if we stall, we need to clear it before
400 * we go on
401 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530402#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000403 display_int_status(us->pusb_dev->status);
404#endif
405 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530406 debug("stalled ->clearing endpoint" \
407 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000408 stat = us->pusb_dev->status;
409 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100410 us->pusb_dev->status = stat;
411 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530412 debug("bulk transferred" \
413 "with error %lX," \
414 " but data ok\n",
415 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000416 return 0;
417 }
418 else
419 return result;
420 }
421 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530422 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000423 return result;
424 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530425 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100426 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530427 debug(" %ld, but data ok\n",
428 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000429 return 0;
430 }
431 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530432 debug(" %ld, data %d\n",
433 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000434 if (!maxtry--)
435 return result;
436 }
437 /* update to show what data was transferred */
438 this_xfer -= partial;
439 buf += partial;
440 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100441 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000442 }
443
444 /* if we get here, we're done and successful */
445 return 0;
446}
447
wdenk149dded2003-09-10 18:20:28 +0000448static int usb_stor_BBB_reset(struct us_data *us)
449{
450 int result;
451 unsigned int pipe;
452
453 /*
454 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
455 *
456 * For Reset Recovery the host shall issue in the following order:
457 * a) a Bulk-Only Mass Storage Reset
458 * b) a Clear Feature HALT to the Bulk-In endpoint
459 * c) a Clear Feature HALT to the Bulk-Out endpoint
460 *
461 * This is done in 3 steps.
462 *
463 * If the reset doesn't succeed, the device should be port reset.
464 *
465 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
466 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530467 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100468 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
469 US_BBB_RESET,
470 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000471 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200472
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100473 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530474 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000475 return -1;
476 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200477
wdenk149dded2003-09-10 18:20:28 +0000478 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000479 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530480 debug("BBB_reset result %d: status %lX reset\n",
481 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000482 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
483 result = usb_clear_halt(us->pusb_dev, pipe);
484 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000485 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530486 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
487 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000488 /* long wait for reset */
489 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
490 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
493 result, us->pusb_dev->status);
494 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000495 return 0;
496}
497
wdenkaffae2b2002-08-17 09:36:01 +0000498/* FIXME: this reset function doesn't really reset the port, and it
499 * should. Actually it should probably do what it's doing here, and
500 * reset the port physically
501 */
502static int usb_stor_CB_reset(struct us_data *us)
503{
504 unsigned char cmd[12];
505 int result;
506
Vivek Gautamceb49722013-04-12 16:34:33 +0530507 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000509 cmd[0] = SCSI_SEND_DIAG;
510 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100511 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
512 US_CBI_ADSC,
513 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
514 0, us->ifnum, cmd, sizeof(cmd),
515 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000516
517 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000518 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530519 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
520 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000521 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
522 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
523
Vivek Gautamceb49722013-04-12 16:34:33 +0530524 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000525 return 0;
526}
527
wdenk149dded2003-09-10 18:20:28 +0000528/*
529 * Set up the command for a BBB device. Note that the actual SCSI
530 * command is copied into cbw.CBWCDB.
531 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600532static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000533{
534 int result;
535 int actlen;
536 int dir_in;
537 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600538 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000539
540 dir_in = US_DIRECTION(srb->cmd[0]);
541
542#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530543 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100544 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
545 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000546 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000548 printf("cmd[%d] %#x ", result, srb->cmd[result]);
549 printf("\n");
550 }
551#endif
552 /* sanity checks */
553 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530554 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000555 return -1;
556 }
557
558 /* always OUT to the ep */
559 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
560
Puneet Saxenaf5766132012-04-03 14:56:06 +0530561 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
562 cbw->dCBWTag = cpu_to_le32(CBWTag++);
563 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
564 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
565 cbw->bCBWLUN = srb->lun;
566 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000567 /* copy the command data into the CBW command data buffer */
568 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300569
Puneet Saxenaf5766132012-04-03 14:56:06 +0530570 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
571 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100572 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000573 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530574 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000575 return result;
576}
577
wdenkaffae2b2002-08-17 09:36:01 +0000578/* FIXME: we also need a CBI_command which sets up the completion
579 * interrupt, and waits for it
580 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600581static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000582{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200583 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100584 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000585 unsigned int pipe;
586 unsigned long status;
587
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100588 retry = 5;
589 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000590
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100591 if (dir_in)
592 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
593 else
594 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
595
596 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530597 debug("CBI gets a command: Try %d\n", 5 - retry);
598#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000599 usb_show_srb(srb);
600#endif
601 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100602 result = usb_control_msg(us->pusb_dev,
603 usb_sndctrlpipe(us->pusb_dev , 0),
604 US_CBI_ADSC,
605 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000606 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100607 srb->cmd, srb->cmdlen,
608 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530609 debug("CB_transport: control msg returned %d, status %lX\n",
610 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000611 /* check the return code for the command */
612 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100613 if (us->pusb_dev->status & USB_ST_STALLED) {
614 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530615 debug(" stall during command found," \
616 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100617 usb_clear_halt(us->pusb_dev,
618 usb_sndctrlpipe(us->pusb_dev, 0));
619 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000620 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530621 debug(" error during command %02X" \
622 " Stat = %lX\n", srb->cmd[0],
623 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000624 return result;
625 }
626 /* transfer the data payload for this command, if one exists*/
627
Vivek Gautamceb49722013-04-12 16:34:33 +0530628 debug("CB_transport: control msg returned %d," \
629 " direction is %s to go 0x%lx\n", result,
630 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000631 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100632 result = us_one_transfer(us, pipe, (char *)srb->pdata,
633 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530634 debug("CBI attempted to transfer data," \
635 " result is %d status %lX, len %d\n",
636 result, us->pusb_dev->status,
637 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100638 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000639 break;
640 } /* if (srb->datalen) */
641 else
642 break;
643 }
644 /* return result */
645
646 return result;
647}
648
649
Simon Glassb9560ad2017-06-14 21:28:30 -0600650static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000651{
652 int timeout;
653
wdenk80885a92004-02-26 23:46:20 +0000654 us->ip_wanted = 1;
Michal Suchanek50dce8f2019-08-18 10:55:26 +0200655 usb_int_msg(us->pusb_dev, us->irqpipe,
Michal Suchanek34371212019-08-18 10:55:27 +0200656 (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
wdenk80885a92004-02-26 23:46:20 +0000657 timeout = 1000;
658 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300659 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000660 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000661 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000662 }
663 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000665 us->ip_wanted = 0;
666 return USB_STOR_TRANSPORT_ERROR;
667 }
Vagrant Cascadiana6f70a32016-03-15 12:16:39 -0700668 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamceb49722013-04-12 16:34:33 +0530669 us->ip_data, us->pusb_dev->irq_act_len,
670 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000671 /* UFI gives us ASC and ASCQ, like a request sense */
672 if (us->subclass == US_SC_UFI) {
673 if (srb->cmd[0] == SCSI_REQ_SENSE ||
674 srb->cmd[0] == SCSI_INQUIRY)
675 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000676 else if (us->ip_data)
677 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000678 else
wdenk80885a92004-02-26 23:46:20 +0000679 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000680 }
681 /* otherwise, we interpret the data normally */
682 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000683 case 0x0001:
684 return USB_STOR_TRANSPORT_GOOD;
685 case 0x0002:
686 return USB_STOR_TRANSPORT_FAILED;
687 default:
688 return USB_STOR_TRANSPORT_ERROR;
689 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000690 return USB_STOR_TRANSPORT_ERROR;
691}
692
693#define USB_TRANSPORT_UNKNOWN_RETRY 5
694#define USB_TRANSPORT_NOT_READY_RETRY 10
695
wdenk149dded2003-09-10 18:20:28 +0000696/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000697static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000698{
wdenk149dded2003-09-10 18:20:28 +0000699 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada8319aeb2016-09-06 22:17:35 +0900700 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
701 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
702 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000703}
704
Simon Glassb9560ad2017-06-14 21:28:30 -0600705static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000706{
707 int result, retry;
708 int dir_in;
709 int actlen, data_actlen;
710 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600711 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000712#ifdef BBB_XPORT_TRACE
713 unsigned char *ptr;
714 int index;
715#endif
716
717 dir_in = US_DIRECTION(srb->cmd[0]);
718
719 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530720 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000721 result = usb_stor_BBB_comdat(srb, us);
722 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530723 debug("failed to send CBW status %ld\n",
724 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
727 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200728 if (!(us->flags & USB_READY))
729 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000730 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
731 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
732 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000733 data_actlen = 0;
734 /* no data, go immediately to the STATUS phase */
735 if (srb->datalen == 0)
736 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530737 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000738 if (dir_in)
739 pipe = pipein;
740 else
741 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300742
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100743 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
744 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000745 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100746 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530747 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000748 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100749 result = usb_stor_BBB_clear_endpt_stall(us,
750 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000751 if (result >= 0)
752 /* continue on to STATUS phase */
753 goto st;
754 }
755 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530756 debug("usb_bulk_msg error status %ld\n",
757 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000758 usb_stor_BBB_reset(us);
759 return USB_STOR_TRANSPORT_FAILED;
760 }
761#ifdef BBB_XPORT_TRACE
762 for (index = 0; index < data_actlen; index++)
763 printf("pdata[%d] %#x ", index, srb->pdata[index]);
764 printf("\n");
765#endif
766 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100767st:
wdenk149dded2003-09-10 18:20:28 +0000768 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100769again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530770 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530771 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200772 &actlen, USB_CNTL_TIMEOUT*5);
773
wdenk149dded2003-09-10 18:20:28 +0000774 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100775 if ((result < 0) && (retry < 1) &&
776 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530777 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000778 /* clear the STALL on the endpoint */
779 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
780 if (result >= 0 && (retry++ < 1))
781 /* do a retry */
782 goto again;
783 }
784 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530785 debug("usb_bulk_msg error status %ld\n",
786 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000787 usb_stor_BBB_reset(us);
788 return USB_STOR_TRANSPORT_FAILED;
789 }
790#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530791 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000792 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
793 printf("ptr[%d] %#x ", index, ptr[index]);
794 printf("\n");
795#endif
796 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530797 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000798 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
799 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530800 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530801 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000802 usb_stor_BBB_reset(us);
803 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530804 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530805 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000806 usb_stor_BBB_reset(us);
807 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530808 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530809 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000810 usb_stor_BBB_reset(us);
811 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530812 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530813 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000814 usb_stor_BBB_reset(us);
815 return USB_STOR_TRANSPORT_FAILED;
816 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530817 debug("transferred %dB instead of %ldB\n",
818 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000819 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530820 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530821 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000822 return USB_STOR_TRANSPORT_FAILED;
823 }
824
825 return result;
826}
827
Simon Glassb9560ad2017-06-14 21:28:30 -0600828static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000829{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100830 int result, status;
Simon Glassb9560ad2017-06-14 21:28:30 -0600831 struct scsi_cmd *psrb;
832 struct scsi_cmd reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100833 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000834
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200835 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100836 status = USB_STOR_TRANSPORT_GOOD;
837 retry = 0;
838 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000839 /* issue the command */
840do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100841 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530842 debug("command / Data returned %d, status %lX\n",
843 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 if (us->protocol == US_PR_CBI) {
846 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530849 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000850 return status;
851 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100852 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
853 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
854 if (!us->ip_data) {
855 /* if the status is good, report it */
856 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530857 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000858 return status;
859 }
860 }
861 }
862 /* do we have to issue an auto request? */
863 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100864 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530865 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000866 us->transport_reset(us);
867 return USB_STOR_TRANSPORT_ERROR;
868 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100869 if ((us->protocol == US_PR_CBI) &&
870 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
871 (srb->cmd[0] == SCSI_INQUIRY))) {
872 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530873 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000874 return USB_STOR_TRANSPORT_GOOD;
875 }
876 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100877 memset(&psrb->cmd[0], 0, 12);
878 psrb->cmd[0] = SCSI_REQ_SENSE;
879 psrb->cmd[1] = srb->lun << 5;
880 psrb->cmd[4] = 18;
881 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200882 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100883 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000884 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100885 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530886 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000887 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100888 if (us->protocol == US_PR_CBI)
889 status = usb_stor_CBI_get_status(psrb, us);
890
891 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530892 debug(" AUTO REQUEST ERROR %ld\n",
893 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000894 return USB_STOR_TRANSPORT_ERROR;
895 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530896 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
897 srb->sense_buf[0], srb->sense_buf[2],
898 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000899 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100900 if ((srb->sense_buf[2] == 0) &&
901 (srb->sense_buf[12] == 0) &&
902 (srb->sense_buf[13] == 0)) {
903 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000904 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100905 }
906
wdenkaffae2b2002-08-17 09:36:01 +0000907 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908 switch (srb->sense_buf[2]) {
909 case 0x01:
910 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000911 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000912 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100913 case 0x02:
914 /* Not Ready */
915 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
916 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
917 " 0x%02X (NOT READY)\n", srb->cmd[0],
918 srb->sense_buf[0], srb->sense_buf[2],
919 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000920 return USB_STOR_TRANSPORT_FAILED;
921 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000922 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000923 goto do_retry;
924 }
925 break;
926 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100927 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
928 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
929 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
930 srb->sense_buf[2], srb->sense_buf[12],
931 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000932 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100933 } else
wdenk149dded2003-09-10 18:20:28 +0000934 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000935 break;
wdenkaffae2b2002-08-17 09:36:01 +0000936 }
937 return USB_STOR_TRANSPORT_FAILED;
938}
939
Bin Mengea7fad92017-09-07 06:13:21 -0700940static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
941 struct us_data *us)
Bin Meng6158d0b2017-09-07 06:13:20 -0700942{
Bin Meng6158d0b2017-09-07 06:13:20 -0700943 /*
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200944 * Limit the total size of a transfer to 120 KB.
945 *
946 * Some devices are known to choke with anything larger. It seems like
947 * the problem stems from the fact that original IDE controllers had
948 * only an 8-bit register to hold the number of sectors in one transfer
949 * and even those couldn't handle a full 256 sectors.
950 *
951 * Because we want to make sure we interoperate with as many devices as
952 * possible, we will maintain a 240 sector transfer size limit for USB
953 * Mass Storage devices.
954 *
955 * Tests show that other operating have similar limits with Microsoft
956 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
957 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
958 * and 2048 for USB3 devices.
Bin Meng6158d0b2017-09-07 06:13:20 -0700959 */
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200960 unsigned short blk = 240;
961
962#if CONFIG_IS_ENABLED(DM_USB)
963 size_t size;
964 int ret;
965
Bin Mengea7fad92017-09-07 06:13:21 -0700966 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200967 if ((ret >= 0) && (size < blk * 512))
Bin Mengea7fad92017-09-07 06:13:21 -0700968 blk = size / 512;
Bin Mengea7fad92017-09-07 06:13:21 -0700969#endif
Bin Meng6158d0b2017-09-07 06:13:20 -0700970
971 us->max_xfer_blk = blk;
972}
wdenkaffae2b2002-08-17 09:36:01 +0000973
Simon Glassb9560ad2017-06-14 21:28:30 -0600974static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000975{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 int retry, i;
977 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000978 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100979 memset(&srb->cmd[0], 0, 12);
980 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200981 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100982 srb->cmd[4] = 36;
983 srb->datalen = 36;
984 srb->cmdlen = 12;
985 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530986 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000988 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200989 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000990
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100991 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000992 printf("error in inquiry\n");
993 return -1;
994 }
995 return 0;
996}
997
Simon Glassb9560ad2017-06-14 21:28:30 -0600998static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000999{
1000 char *ptr;
wdenk80885a92004-02-26 23:46:20 +00001001
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001002 ptr = (char *)srb->pdata;
1003 memset(&srb->cmd[0], 0, 12);
1004 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001005 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001006 srb->cmd[4] = 18;
1007 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +02001008 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001009 srb->cmdlen = 12;
1010 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +05301011 debug("Request Sense returned %02X %02X %02X\n",
1012 srb->sense_buf[2], srb->sense_buf[12],
1013 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001014 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001015 return 0;
1016}
1017
Simon Glassb9560ad2017-06-14 21:28:30 -06001018static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001019{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001020 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001021
wdenkaffae2b2002-08-17 09:36:01 +00001022 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001023 memset(&srb->cmd[0], 0, 12);
1024 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001025 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001026 srb->datalen = 0;
1027 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001028 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1029 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001030 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001031 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001032 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -08001033 /*
1034 * Check the Key Code Qualifier, if it matches
1035 * "Not Ready - medium not present"
1036 * (the sense Key equals 0x2 and the ASC is 0x3a)
1037 * return immediately as the medium being absent won't change
1038 * unless there is a user action.
1039 */
1040 if ((srb->sense_buf[2] == 0x02) &&
1041 (srb->sense_buf[12] == 0x3a))
1042 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +00001043 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001045
wdenkaffae2b2002-08-17 09:36:01 +00001046 return -1;
1047}
1048
Simon Glassb9560ad2017-06-14 21:28:30 -06001049static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001050{
1051 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001052 /* XXX retries */
1053 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001054 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 memset(&srb->cmd[0], 0, 12);
1056 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001057 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001058 srb->datalen = 8;
1059 srb->cmdlen = 12;
1060 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001061 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001062 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001063
wdenkaffae2b2002-08-17 09:36:01 +00001064 return -1;
1065}
1066
Simon Glassb9560ad2017-06-14 21:28:30 -06001067static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1068 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001069{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001070 memset(&srb->cmd[0], 0, 12);
1071 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001072 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001073 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1074 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1075 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1076 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1077 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1078 srb->cmd[8] = (unsigned char) blocks & 0xff;
1079 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301080 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001081 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001082}
1083
Simon Glassb9560ad2017-06-14 21:28:30 -06001084static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1085 unsigned long start, unsigned short blocks)
Mahavir Jain127e1082009-11-03 12:22:10 +05301086{
1087 memset(&srb->cmd[0], 0, 12);
1088 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001089 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301090 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1091 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1092 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1093 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1094 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1095 srb->cmd[8] = (unsigned char) blocks & 0xff;
1096 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301097 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301098 return ss->transport(srb, ss);
1099}
1100
wdenkaffae2b2002-08-17 09:36:01 +00001101
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001102#ifdef CONFIG_USB_BIN_FIXUP
1103/*
1104 * Some USB storage devices queried for SCSI identification data respond with
1105 * binary strings, which if output to the console freeze the terminal. The
1106 * workaround is to modify the vendor and product strings read from such
1107 * device with proper values (as reported by 'usb info').
1108 *
1109 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001110 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001111 */
1112static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1113 unsigned char vendor[],
1114 unsigned char product[]) {
1115 const unsigned char max_vendor_len = 40;
1116 const unsigned char max_product_len = 20;
1117 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001118 strncpy((char *)vendor, "SMSC", max_vendor_len);
1119 strncpy((char *)product, "Flash Media Cntrller",
1120 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001121 }
1122}
1123#endif /* CONFIG_USB_BIN_FIXUP */
1124
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001125#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001126static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1127 lbaint_t blkcnt, void *buffer)
1128#else
Simon Glass4101f682016-02-29 15:25:34 -07001129static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001130 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001131#endif
wdenkaffae2b2002-08-17 09:36:01 +00001132{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001133 lbaint_t start, blks;
1134 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001135 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001136 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001137 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001138 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001139 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001140#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001141 struct blk_desc *block_dev;
1142#endif
wdenkf8d813e2004-03-02 14:05:39 +00001143
1144 if (blkcnt == 0)
1145 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001146 /* Setup device */
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001147#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001148 block_dev = dev_get_uclass_platdata(dev);
1149 udev = dev_get_parent_priv(dev_get_parent(dev));
1150 debug("\nusb_read: udev %d\n", block_dev->devnum);
1151#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001152 debug("\nusb_read: udev %d\n", block_dev->devnum);
1153 udev = usb_dev_desc[block_dev->devnum].priv;
1154 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001155 debug("%s: No device\n", __func__);
1156 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001157 }
Simon Glass07b2b782016-02-29 15:25:58 -07001158#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001159 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001160
1161 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut31232de2020-04-06 14:29:44 +02001162 usb_lock_async(udev, 1);
Simon Glass9807c3b2016-02-29 15:25:54 -07001163 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001164 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001165 start = blknr;
1166 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001167
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001168 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1169 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001170
wdenkaffae2b2002-08-17 09:36:01 +00001171 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001172 /* XXX need some comment here */
1173 retry = 2;
1174 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001175 if (blks > ss->max_xfer_blk)
1176 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001177 else
1178 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001179retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001180 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001181 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001182 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001183 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001184 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301185 debug("Read ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001186 ss->flags &= ~USB_READY;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001187 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001188 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001189 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001190 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001191 break;
1192 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001193 start += smallblks;
1194 blks -= smallblks;
1195 buf_addr += srb->datalen;
1196 } while (blks != 0);
1197
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001198 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301199 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001200
Marek Vasut31232de2020-04-06 14:29:44 +02001201 usb_lock_async(udev, 0);
wdenkaffae2b2002-08-17 09:36:01 +00001202 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001203 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001204 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001205 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001206}
1207
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001208#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001209static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1210 lbaint_t blkcnt, const void *buffer)
1211#else
Simon Glass4101f682016-02-29 15:25:34 -07001212static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001213 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001214#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301215{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001216 lbaint_t start, blks;
1217 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301218 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001219 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001220 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001221 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001222 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001223#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001224 struct blk_desc *block_dev;
1225#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301226
1227 if (blkcnt == 0)
1228 return 0;
1229
Mahavir Jain127e1082009-11-03 12:22:10 +05301230 /* Setup device */
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001231#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001232 block_dev = dev_get_uclass_platdata(dev);
1233 udev = dev_get_parent_priv(dev_get_parent(dev));
1234 debug("\nusb_read: udev %d\n", block_dev->devnum);
1235#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001236 debug("\nusb_read: udev %d\n", block_dev->devnum);
1237 udev = usb_dev_desc[block_dev->devnum].priv;
1238 if (!udev) {
1239 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001240 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001241 }
Simon Glass07b2b782016-02-29 15:25:58 -07001242#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001243 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301244
1245 usb_disable_asynch(1); /* asynch transfer not allowed */
Marek Vasut31232de2020-04-06 14:29:44 +02001246 usb_lock_async(udev, 1);
Mahavir Jain127e1082009-11-03 12:22:10 +05301247
Simon Glass9807c3b2016-02-29 15:25:54 -07001248 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001249 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301250 start = blknr;
1251 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301252
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001253 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1254 block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301255
1256 do {
1257 /* If write fails retry for max retry count else
1258 * return with number of blocks written successfully.
1259 */
1260 retry = 2;
1261 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001262 if (blks > ss->max_xfer_blk)
1263 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301264 else
1265 smallblks = (unsigned short) blks;
1266retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001267 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301268 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001269 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301270 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001271 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301272 debug("Write ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001273 ss->flags &= ~USB_READY;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001274 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301275 if (retry--)
1276 goto retry_it;
1277 blkcnt -= blks;
1278 break;
1279 }
1280 start += smallblks;
1281 blks -= smallblks;
1282 buf_addr += srb->datalen;
1283 } while (blks != 0);
1284
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001285 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1286 start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301287
Marek Vasut31232de2020-04-06 14:29:44 +02001288 usb_lock_async(udev, 0);
Mahavir Jain127e1082009-11-03 12:22:10 +05301289 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001290 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001291 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301292 return blkcnt;
1293
1294}
wdenkaffae2b2002-08-17 09:36:01 +00001295
1296/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001297int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1298 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001299{
Tom Rix8f8bd562009-10-31 12:37:38 -05001300 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001301 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301302 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001303 unsigned int flags = 0;
1304
wdenkaffae2b2002-08-17 09:36:01 +00001305 /* let's examine the device now */
1306 iface = &dev->config.if_desc[ifnum];
1307
wdenkaffae2b2002-08-17 09:36:01 +00001308 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001309 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1310 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1311 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001312 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001313 /* if it's not a mass storage, we go no further */
1314 return 0;
1315 }
1316
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001317 memset(ss, 0, sizeof(struct us_data));
1318
wdenkaffae2b2002-08-17 09:36:01 +00001319 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301320 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001321
1322 /* Initialize the us_data structure with some useful info */
1323 ss->flags = flags;
1324 ss->ifnum = ifnum;
1325 ss->pusb_dev = dev;
1326 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001327 ss->subclass = iface->desc.bInterfaceSubClass;
1328 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001329
1330 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301331 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001332 switch (ss->protocol) {
1333 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301334 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001335 ss->transport = usb_stor_CB_transport;
1336 ss->transport_reset = usb_stor_CB_reset;
1337 break;
1338
1339 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301340 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001341 ss->transport = usb_stor_CB_transport;
1342 ss->transport_reset = usb_stor_CB_reset;
1343 break;
wdenk149dded2003-09-10 18:20:28 +00001344 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301345 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001346 ss->transport = usb_stor_BBB_transport;
1347 ss->transport_reset = usb_stor_BBB_reset;
1348 break;
wdenkaffae2b2002-08-17 09:36:01 +00001349 default:
wdenk80885a92004-02-26 23:46:20 +00001350 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001351 return 0;
1352 break;
1353 }
1354
1355 /*
1356 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1357 * An optional interrupt is OK (necessary for CBI protocol).
1358 * We will ignore any others.
1359 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001360 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301361 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001362 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301363 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001364 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301365 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1366 ss->ep_in = ep_desc->bEndpointAddress &
1367 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001368 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001369 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301370 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001371 USB_ENDPOINT_NUMBER_MASK;
1372 }
1373
1374 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301375 if ((ep_desc->bmAttributes &
1376 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1377 ss->ep_int = ep_desc->bEndpointAddress &
1378 USB_ENDPOINT_NUMBER_MASK;
1379 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001380 }
1381 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301382 debug("Endpoints In %d Out %d Int %d\n",
1383 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001384
1385 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001386 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001387 !ss->ep_in || !ss->ep_out ||
1388 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301389 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001390 return 0;
1391 }
1392 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001393 /* We only handle certain protocols. Currently, these are
1394 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001395 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001396 */
wdenk80885a92004-02-26 23:46:20 +00001397 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1398 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001399 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001400 return 0;
1401 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001402 if (ss->ep_int) {
1403 /* we had found an interrupt endpoint, prepare irq pipe
1404 * set up the IRQ pipe and handler
1405 */
wdenkaffae2b2002-08-17 09:36:01 +00001406 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1407 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1408 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001409 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001410 }
Bin Meng6158d0b2017-09-07 06:13:20 -07001411
1412 /* Set the maximum transfer size per host controller setting */
Bin Mengea7fad92017-09-07 06:13:21 -07001413 usb_stor_set_max_xfer_blk(dev, ss);
Bin Meng6158d0b2017-09-07 06:13:20 -07001414
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001415 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001416 return 1;
1417}
1418
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001419int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001420 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001421{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001422 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001423 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1424 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1425 u32 capacity, blksz;
Simon Glassb9560ad2017-06-14 21:28:30 -06001426 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001427
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001428 pccb->pdata = usb_stor_buf;
1429
1430 dev_desc->target = dev->devnum;
1431 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301432 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001433
Simon Glass1d5827a2015-03-25 12:22:12 -06001434 if (usb_inquiry(pccb, ss)) {
1435 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001436 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001437 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001438
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001439 perq = usb_stor_buf[0];
1440 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001441
Soeren Moch6a559bb2014-11-08 07:02:14 +01001442 /*
1443 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1444 * they would not respond to test_unit_ready .
1445 */
1446 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001447 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001448 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001449 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001450 if ((modi&0x80) == 0x80) {
1451 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001452 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001453 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001454 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1455 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1456 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001457 dev_desc->vendor[8] = 0;
1458 dev_desc->product[16] = 0;
1459 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001460#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001461 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1462 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001463#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301464 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1465 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001466 if (usb_test_unit_ready(pccb, ss)) {
1467 printf("Device NOT ready\n"
1468 " Request Sense returned %02X %02X %02X\n",
1469 pccb->sense_buf[2], pccb->sense_buf[12],
1470 pccb->sense_buf[13]);
Troy Kisky1e5eca72017-04-10 18:23:11 -07001471 if (dev_desc->removable == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001472 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001473 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001474 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001475 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001476 memset(pccb->pdata, 0, 8);
1477 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001478 printf("READ_CAP ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001479 ss->flags &= ~USB_READY;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001480 cap[0] = 2880;
1481 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001482 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001483 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001484#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001485 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1486 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001487
Christian Eggersc9182612008-05-21 22:12:00 +02001488 cap[0] = cpu_to_be32(cap[0]);
1489 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001490#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001491
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001492 capacity = be32_to_cpu(cap[0]) + 1;
1493 blksz = be32_to_cpu(cap[1]);
1494
1495 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1496 dev_desc->lba = capacity;
1497 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001498 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001499 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301500 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001501
wdenkaffae2b2002-08-17 09:36:01 +00001502 return 1;
1503}
Simon Glassacf277a2015-03-25 12:22:16 -06001504
Sven Schwermerfd09c202018-11-21 08:43:56 +01001505#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassacf277a2015-03-25 12:22:16 -06001506
1507static int usb_mass_storage_probe(struct udevice *dev)
1508{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001509 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001510 int ret;
1511
1512 usb_disable_asynch(1); /* asynch transfer not allowed */
1513 ret = usb_stor_probe_device(udev);
1514 usb_disable_asynch(0); /* asynch transfer allowed */
1515
1516 return ret;
1517}
1518
1519static const struct udevice_id usb_mass_storage_ids[] = {
1520 { .compatible = "usb-mass-storage" },
1521 { }
1522};
1523
1524U_BOOT_DRIVER(usb_mass_storage) = {
1525 .name = "usb_mass_storage",
1526 .id = UCLASS_MASS_STORAGE,
1527 .of_match = usb_mass_storage_ids,
1528 .probe = usb_mass_storage_probe,
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001529#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001530 .platdata_auto_alloc_size = sizeof(struct us_data),
1531#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001532};
1533
1534UCLASS_DRIVER(usb_mass_storage) = {
1535 .id = UCLASS_MASS_STORAGE,
1536 .name = "usb_mass_storage",
1537};
1538
1539static const struct usb_device_id mass_storage_id_table[] = {
1540 {
1541 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1542 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1543 },
1544 { } /* Terminating entry */
1545};
1546
Simon Glassabb59cf2015-07-06 16:47:51 -06001547U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001548#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001549
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001550#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001551static const struct blk_ops usb_storage_ops = {
1552 .read = usb_stor_read,
1553 .write = usb_stor_write,
1554};
1555
1556U_BOOT_DRIVER(usb_storage_blk) = {
1557 .name = "usb_storage_blk",
1558 .id = UCLASS_BLK,
1559 .ops = &usb_storage_ops,
1560};
Simon Glassc0543bf2016-05-01 11:36:06 -06001561#else
1562U_BOOT_LEGACY_BLK(usb) = {
1563 .if_typename = "usb",
1564 .if_type = IF_TYPE_USB,
1565 .max_devs = USB_MAX_STOR_DEV,
1566 .desc = usb_dev_desc,
1567};
Simon Glassacf277a2015-03-25 12:22:16 -06001568#endif