blob: 097b6729c14d14c1dfd968499e056d8b07b60775 [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{
Bin Meng6158d0b2017-09-07 06:13:20 -0700941 /*
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200942 * Limit the total size of a transfer to 120 KB.
943 *
944 * Some devices are known to choke with anything larger. It seems like
945 * the problem stems from the fact that original IDE controllers had
946 * only an 8-bit register to hold the number of sectors in one transfer
947 * and even those couldn't handle a full 256 sectors.
948 *
949 * Because we want to make sure we interoperate with as many devices as
950 * possible, we will maintain a 240 sector transfer size limit for USB
951 * Mass Storage devices.
952 *
953 * Tests show that other operating have similar limits with Microsoft
954 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
955 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
956 * and 2048 for USB3 devices.
Bin Meng6158d0b2017-09-07 06:13:20 -0700957 */
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200958 unsigned short blk = 240;
959
960#if CONFIG_IS_ENABLED(DM_USB)
961 size_t size;
962 int ret;
963
Bin Mengea7fad92017-09-07 06:13:21 -0700964 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
Marek Vasut7d6fd7f2019-09-16 00:16:25 +0200965 if ((ret >= 0) && (size < blk * 512))
Bin Mengea7fad92017-09-07 06:13:21 -0700966 blk = size / 512;
Bin Mengea7fad92017-09-07 06:13:21 -0700967#endif
Bin Meng6158d0b2017-09-07 06:13:20 -0700968
969 us->max_xfer_blk = blk;
970}
wdenkaffae2b2002-08-17 09:36:01 +0000971
Simon Glassb9560ad2017-06-14 21:28:30 -0600972static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000973{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100974 int retry, i;
975 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000976 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100977 memset(&srb->cmd[0], 0, 12);
978 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200979 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100980 srb->cmd[4] = 36;
981 srb->datalen = 36;
982 srb->cmdlen = 12;
983 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530984 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100985 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000986 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200987 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000988
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100989 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000990 printf("error in inquiry\n");
991 return -1;
992 }
993 return 0;
994}
995
Simon Glassb9560ad2017-06-14 21:28:30 -0600996static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000997{
998 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000999
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001000 ptr = (char *)srb->pdata;
1001 memset(&srb->cmd[0], 0, 12);
1002 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001003 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001004 srb->cmd[4] = 18;
1005 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +02001006 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001007 srb->cmdlen = 12;
1008 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +05301009 debug("Request Sense returned %02X %02X %02X\n",
1010 srb->sense_buf[2], srb->sense_buf[12],
1011 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001012 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001013 return 0;
1014}
1015
Simon Glassb9560ad2017-06-14 21:28:30 -06001016static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001017{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001018 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001019
wdenkaffae2b2002-08-17 09:36:01 +00001020 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001021 memset(&srb->cmd[0], 0, 12);
1022 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001023 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001024 srb->datalen = 0;
1025 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001026 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1027 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001028 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001029 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001030 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -08001031 /*
1032 * Check the Key Code Qualifier, if it matches
1033 * "Not Ready - medium not present"
1034 * (the sense Key equals 0x2 and the ASC is 0x3a)
1035 * return immediately as the medium being absent won't change
1036 * unless there is a user action.
1037 */
1038 if ((srb->sense_buf[2] == 0x02) &&
1039 (srb->sense_buf[12] == 0x3a))
1040 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +00001041 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001042 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001043
wdenkaffae2b2002-08-17 09:36:01 +00001044 return -1;
1045}
1046
Simon Glassb9560ad2017-06-14 21:28:30 -06001047static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001048{
1049 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 /* XXX retries */
1051 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001052 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001053 memset(&srb->cmd[0], 0, 12);
1054 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001055 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001056 srb->datalen = 8;
1057 srb->cmdlen = 12;
1058 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001059 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001060 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001061
wdenkaffae2b2002-08-17 09:36:01 +00001062 return -1;
1063}
1064
Simon Glassb9560ad2017-06-14 21:28:30 -06001065static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1066 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001067{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001068 memset(&srb->cmd[0], 0, 12);
1069 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001070 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001071 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1072 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1073 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1074 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1075 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1076 srb->cmd[8] = (unsigned char) blocks & 0xff;
1077 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301078 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001080}
1081
Simon Glassb9560ad2017-06-14 21:28:30 -06001082static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1083 unsigned long start, unsigned short blocks)
Mahavir Jain127e1082009-11-03 12:22:10 +05301084{
1085 memset(&srb->cmd[0], 0, 12);
1086 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001087 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301088 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1089 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1090 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1091 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1092 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1093 srb->cmd[8] = (unsigned char) blocks & 0xff;
1094 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301095 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301096 return ss->transport(srb, ss);
1097}
1098
wdenkaffae2b2002-08-17 09:36:01 +00001099
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001100#ifdef CONFIG_USB_BIN_FIXUP
1101/*
1102 * Some USB storage devices queried for SCSI identification data respond with
1103 * binary strings, which if output to the console freeze the terminal. The
1104 * workaround is to modify the vendor and product strings read from such
1105 * device with proper values (as reported by 'usb info').
1106 *
1107 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001108 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001109 */
1110static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1111 unsigned char vendor[],
1112 unsigned char product[]) {
1113 const unsigned char max_vendor_len = 40;
1114 const unsigned char max_product_len = 20;
1115 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001116 strncpy((char *)vendor, "SMSC", max_vendor_len);
1117 strncpy((char *)product, "Flash Media Cntrller",
1118 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001119 }
1120}
1121#endif /* CONFIG_USB_BIN_FIXUP */
1122
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001123#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001124static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1125 lbaint_t blkcnt, void *buffer)
1126#else
Simon Glass4101f682016-02-29 15:25:34 -07001127static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001128 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001129#endif
wdenkaffae2b2002-08-17 09:36:01 +00001130{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001131 lbaint_t start, blks;
1132 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001133 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001134 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001135 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001136 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001137 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001138#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001139 struct blk_desc *block_dev;
1140#endif
wdenkf8d813e2004-03-02 14:05:39 +00001141
1142 if (blkcnt == 0)
1143 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001144 /* Setup device */
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001145#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001146 block_dev = dev_get_uclass_platdata(dev);
1147 udev = dev_get_parent_priv(dev_get_parent(dev));
1148 debug("\nusb_read: udev %d\n", block_dev->devnum);
1149#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001150 debug("\nusb_read: udev %d\n", block_dev->devnum);
1151 udev = usb_dev_desc[block_dev->devnum].priv;
1152 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001153 debug("%s: No device\n", __func__);
1154 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001155 }
Simon Glass07b2b782016-02-29 15:25:58 -07001156#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001157 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001158
1159 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass9807c3b2016-02-29 15:25:54 -07001160 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001161 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001162 start = blknr;
1163 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001164
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001165 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1166 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001167
wdenkaffae2b2002-08-17 09:36:01 +00001168 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001169 /* XXX need some comment here */
1170 retry = 2;
1171 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001172 if (blks > ss->max_xfer_blk)
1173 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001174 else
1175 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001176retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001177 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001178 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001179 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001180 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001181 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301182 debug("Read ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001183 ss->flags &= ~USB_READY;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001184 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001185 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001186 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001187 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001188 break;
1189 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001190 start += smallblks;
1191 blks -= smallblks;
1192 buf_addr += srb->datalen;
1193 } while (blks != 0);
1194
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001195 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301196 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001197
wdenkaffae2b2002-08-17 09:36:01 +00001198 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001199 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001200 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001201 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001202}
1203
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001204#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001205static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1206 lbaint_t blkcnt, const void *buffer)
1207#else
Simon Glass4101f682016-02-29 15:25:34 -07001208static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001209 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001210#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301211{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001212 lbaint_t start, blks;
1213 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301214 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001215 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001216 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001217 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001218 struct scsi_cmd *srb = &usb_ccb;
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001219#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001220 struct blk_desc *block_dev;
1221#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301222
1223 if (blkcnt == 0)
1224 return 0;
1225
Mahavir Jain127e1082009-11-03 12:22:10 +05301226 /* Setup device */
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001227#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001228 block_dev = dev_get_uclass_platdata(dev);
1229 udev = dev_get_parent_priv(dev_get_parent(dev));
1230 debug("\nusb_read: udev %d\n", block_dev->devnum);
1231#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001232 debug("\nusb_read: udev %d\n", block_dev->devnum);
1233 udev = usb_dev_desc[block_dev->devnum].priv;
1234 if (!udev) {
1235 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001236 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001237 }
Simon Glass07b2b782016-02-29 15:25:58 -07001238#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001239 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301240
1241 usb_disable_asynch(1); /* asynch transfer not allowed */
1242
Simon Glass9807c3b2016-02-29 15:25:54 -07001243 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001244 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301245 start = blknr;
1246 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301247
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001248 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1249 block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301250
1251 do {
1252 /* If write fails retry for max retry count else
1253 * return with number of blocks written successfully.
1254 */
1255 retry = 2;
1256 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001257 if (blks > ss->max_xfer_blk)
1258 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301259 else
1260 smallblks = (unsigned short) blks;
1261retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001262 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301263 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001264 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301265 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001266 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301267 debug("Write ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001268 ss->flags &= ~USB_READY;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001269 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301270 if (retry--)
1271 goto retry_it;
1272 blkcnt -= blks;
1273 break;
1274 }
1275 start += smallblks;
1276 blks -= smallblks;
1277 buf_addr += srb->datalen;
1278 } while (blks != 0);
1279
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001280 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1281 start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301282
1283 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001284 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001285 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301286 return blkcnt;
1287
1288}
wdenkaffae2b2002-08-17 09:36:01 +00001289
1290/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001291int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1292 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001293{
Tom Rix8f8bd562009-10-31 12:37:38 -05001294 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001295 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301296 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001297 unsigned int flags = 0;
1298
wdenkaffae2b2002-08-17 09:36:01 +00001299 /* let's examine the device now */
1300 iface = &dev->config.if_desc[ifnum];
1301
wdenkaffae2b2002-08-17 09:36:01 +00001302 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001303 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1304 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1305 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001306 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001307 /* if it's not a mass storage, we go no further */
1308 return 0;
1309 }
1310
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001311 memset(ss, 0, sizeof(struct us_data));
1312
wdenkaffae2b2002-08-17 09:36:01 +00001313 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301314 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001315
1316 /* Initialize the us_data structure with some useful info */
1317 ss->flags = flags;
1318 ss->ifnum = ifnum;
1319 ss->pusb_dev = dev;
1320 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001321 ss->subclass = iface->desc.bInterfaceSubClass;
1322 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001323
1324 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301325 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001326 switch (ss->protocol) {
1327 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301328 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001329 ss->transport = usb_stor_CB_transport;
1330 ss->transport_reset = usb_stor_CB_reset;
1331 break;
1332
1333 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301334 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001335 ss->transport = usb_stor_CB_transport;
1336 ss->transport_reset = usb_stor_CB_reset;
1337 break;
wdenk149dded2003-09-10 18:20:28 +00001338 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301339 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001340 ss->transport = usb_stor_BBB_transport;
1341 ss->transport_reset = usb_stor_BBB_reset;
1342 break;
wdenkaffae2b2002-08-17 09:36:01 +00001343 default:
wdenk80885a92004-02-26 23:46:20 +00001344 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001345 return 0;
1346 break;
1347 }
1348
1349 /*
1350 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1351 * An optional interrupt is OK (necessary for CBI protocol).
1352 * We will ignore any others.
1353 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001354 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301355 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001356 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301357 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001358 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301359 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1360 ss->ep_in = ep_desc->bEndpointAddress &
1361 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001362 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001363 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301364 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001365 USB_ENDPOINT_NUMBER_MASK;
1366 }
1367
1368 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301369 if ((ep_desc->bmAttributes &
1370 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1371 ss->ep_int = ep_desc->bEndpointAddress &
1372 USB_ENDPOINT_NUMBER_MASK;
1373 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001374 }
1375 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301376 debug("Endpoints In %d Out %d Int %d\n",
1377 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001378
1379 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001380 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001381 !ss->ep_in || !ss->ep_out ||
1382 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301383 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001384 return 0;
1385 }
1386 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001387 /* We only handle certain protocols. Currently, these are
1388 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001389 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001390 */
wdenk80885a92004-02-26 23:46:20 +00001391 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1392 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001393 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001394 return 0;
1395 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001396 if (ss->ep_int) {
1397 /* we had found an interrupt endpoint, prepare irq pipe
1398 * set up the IRQ pipe and handler
1399 */
wdenkaffae2b2002-08-17 09:36:01 +00001400 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1401 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1402 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001403 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001404 }
Bin Meng6158d0b2017-09-07 06:13:20 -07001405
1406 /* Set the maximum transfer size per host controller setting */
Bin Mengea7fad92017-09-07 06:13:21 -07001407 usb_stor_set_max_xfer_blk(dev, ss);
Bin Meng6158d0b2017-09-07 06:13:20 -07001408
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001409 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001410 return 1;
1411}
1412
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001413int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001414 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001415{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001416 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001417 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1418 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1419 u32 capacity, blksz;
Simon Glassb9560ad2017-06-14 21:28:30 -06001420 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001421
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001422 pccb->pdata = usb_stor_buf;
1423
1424 dev_desc->target = dev->devnum;
1425 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301426 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001427
Simon Glass1d5827a2015-03-25 12:22:12 -06001428 if (usb_inquiry(pccb, ss)) {
1429 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001430 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001431 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001432
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001433 perq = usb_stor_buf[0];
1434 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001435
Soeren Moch6a559bb2014-11-08 07:02:14 +01001436 /*
1437 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1438 * they would not respond to test_unit_ready .
1439 */
1440 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001441 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001442 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001443 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001444 if ((modi&0x80) == 0x80) {
1445 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001446 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001447 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001448 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1449 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1450 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001451 dev_desc->vendor[8] = 0;
1452 dev_desc->product[16] = 0;
1453 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001454#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001455 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1456 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001457#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301458 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1459 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001460 if (usb_test_unit_ready(pccb, ss)) {
1461 printf("Device NOT ready\n"
1462 " Request Sense returned %02X %02X %02X\n",
1463 pccb->sense_buf[2], pccb->sense_buf[12],
1464 pccb->sense_buf[13]);
Troy Kisky1e5eca72017-04-10 18:23:11 -07001465 if (dev_desc->removable == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001466 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001467 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001468 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001469 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001470 memset(pccb->pdata, 0, 8);
1471 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001472 printf("READ_CAP ERROR\n");
Marek Vasutda3d1c42019-10-05 19:18:38 +02001473 ss->flags &= ~USB_READY;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001474 cap[0] = 2880;
1475 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001476 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001477 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001478#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001479 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1480 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001481
Christian Eggersc9182612008-05-21 22:12:00 +02001482 cap[0] = cpu_to_be32(cap[0]);
1483 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001484#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001485
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001486 capacity = be32_to_cpu(cap[0]) + 1;
1487 blksz = be32_to_cpu(cap[1]);
1488
1489 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1490 dev_desc->lba = capacity;
1491 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001492 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001493 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301494 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001495
wdenkaffae2b2002-08-17 09:36:01 +00001496 return 1;
1497}
Simon Glassacf277a2015-03-25 12:22:16 -06001498
Sven Schwermerfd09c202018-11-21 08:43:56 +01001499#if CONFIG_IS_ENABLED(DM_USB)
Simon Glassacf277a2015-03-25 12:22:16 -06001500
1501static int usb_mass_storage_probe(struct udevice *dev)
1502{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001503 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001504 int ret;
1505
1506 usb_disable_asynch(1); /* asynch transfer not allowed */
1507 ret = usb_stor_probe_device(udev);
1508 usb_disable_asynch(0); /* asynch transfer allowed */
1509
1510 return ret;
1511}
1512
1513static const struct udevice_id usb_mass_storage_ids[] = {
1514 { .compatible = "usb-mass-storage" },
1515 { }
1516};
1517
1518U_BOOT_DRIVER(usb_mass_storage) = {
1519 .name = "usb_mass_storage",
1520 .id = UCLASS_MASS_STORAGE,
1521 .of_match = usb_mass_storage_ids,
1522 .probe = usb_mass_storage_probe,
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001523#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001524 .platdata_auto_alloc_size = sizeof(struct us_data),
1525#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001526};
1527
1528UCLASS_DRIVER(usb_mass_storage) = {
1529 .id = UCLASS_MASS_STORAGE,
1530 .name = "usb_mass_storage",
1531};
1532
1533static const struct usb_device_id mass_storage_id_table[] = {
1534 {
1535 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1536 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1537 },
1538 { } /* Terminating entry */
1539};
1540
Simon Glassabb59cf2015-07-06 16:47:51 -06001541U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001542#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001543
Sven Schwermer1af9bfd2018-11-21 08:43:57 +01001544#if CONFIG_IS_ENABLED(BLK)
Simon Glass07b2b782016-02-29 15:25:58 -07001545static const struct blk_ops usb_storage_ops = {
1546 .read = usb_stor_read,
1547 .write = usb_stor_write,
1548};
1549
1550U_BOOT_DRIVER(usb_storage_blk) = {
1551 .name = "usb_storage_blk",
1552 .id = UCLASS_BLK,
1553 .ops = &usb_storage_ops,
1554};
Simon Glassc0543bf2016-05-01 11:36:06 -06001555#else
1556U_BOOT_LEGACY_BLK(usb) = {
1557 .if_typename = "usb",
1558 .if_type = IF_TYPE_USB,
1559 .max_devs = USB_MAX_STOR_DEV,
1560 .desc = usb_dev_desc,
1561};
Simon Glassacf277a2015-03-25 12:22:16 -06001562#endif