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