blob: d92ebb6eb19043fba3851885ea8dfc94652c50c8 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00002/*
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +02003 * Most of this source has been derived from the Linux USB
4 * project:
5 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
6 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
7 * (c) 1999 Michael Gee (michael@linuxspecific.com)
8 * (c) 2000 Yggdrasil Computing, Inc.
9 *
10 *
11 * Adapted for U-Boot:
12 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
Simon Glassac9774e2015-03-25 12:22:16 -060013 * Driver model conversion:
14 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000015 *
wdenkde887eb2003-09-10 18:20:28 +000016 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020017 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000018 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020019 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000020 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000021 */
22
23/* Note:
24 * Currently only the CBI transport protocoll has been implemented, and it
25 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
26 * transport protocoll may work as well.
27 */
wdenkde887eb2003-09-10 18:20:28 +000028/*
29 * New Note:
30 * Support for USB Mass Storage Devices (BBB) has been added. It has
31 * only been tested with USB memory sticks.
wdenkde887eb2003-09-10 18:20:28 +000032 */
wdenkaffae2b2002-08-17 09:36:01 +000033
34
wdenkaffae2b2002-08-17 09:36:01 +000035#include <common.h>
36#include <command.h>
Simon Glassac9774e2015-03-25 12:22:16 -060037#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060038#include <errno.h>
Simon Glass332a9b62015-03-25 12:22:14 -060039#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060040#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020041#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000042#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060043#include <dm/device-internal.h>
Simon Glass01f5be92016-02-29 15:25:58 -070044#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000045
Grant Likelyffc2dd72007-02-20 09:04:34 +010046#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000047#include <usb.h>
48
wdenk5f495752004-02-26 23:46:20 +000049#undef BBB_COMDAT_TRACE
50#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000051
wdenkaffae2b2002-08-17 09:36:01 +000052#include <scsi.h>
53/* direction table -- this indicates the direction of the data
54 * transfer for each command code -- a 1 indicates input
55 */
Mike Frysinger165522b2010-10-20 07:16:04 -040056static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000057 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
58 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
61};
62#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
63
Simon Glass5fb559d2017-06-14 21:28:30 -060064static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchi956a4352008-12-10 15:52:06 +010065static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000066
Michael Trimarchi956a4352008-12-10 15:52:06 +010067static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000068
Simon Glass01f5be92016-02-29 15:25:58 -070069#ifndef CONFIG_BLK
Simon Glasse3394752016-02-29 15:25:34 -070070static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -070071#endif
wdenkaffae2b2002-08-17 09:36:01 +000072
73struct us_data;
Simon Glass5fb559d2017-06-14 21:28:30 -060074typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchi956a4352008-12-10 15:52:06 +010075typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000076
77struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010078 struct usb_device *pusb_dev; /* this usb_device */
79
80 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020081# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010082 unsigned char ifnum; /* interface number */
83 unsigned char ep_in; /* in endpoint */
84 unsigned char ep_out; /* out ....... */
85 unsigned char ep_int; /* interrupt . */
86 unsigned char subclass; /* as in overview */
87 unsigned char protocol; /* .............. */
88 unsigned char attention_done; /* force attn on first cmd */
89 unsigned short ip_data; /* interrupt data */
90 int action; /* what to do */
91 int ip_wanted; /* needed */
92 int *irq_handle; /* for USB int requests */
93 unsigned int irqpipe; /* pipe for release_irq */
94 unsigned char irqmaxp; /* max packed for irq Pipe */
95 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glass5fb559d2017-06-14 21:28:30 -060096 struct scsi_cmd *srb; /* current srb */
Michael Trimarchi956a4352008-12-10 15:52:06 +010097 trans_reset transport_reset; /* reset routine */
98 trans_cmnd transport; /* transport routine */
Bin Mengf6e373e2017-09-07 06:13:20 -070099 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000100};
101
Simon Glass01f5be92016-02-29 15:25:58 -0700102#ifndef CONFIG_BLK
wdenkaffae2b2002-08-17 09:36:01 +0000103static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass01f5be92016-02-29 15:25:58 -0700104#endif
wdenkaffae2b2002-08-17 09:36:01 +0000105
wdenk5f495752004-02-26 23:46:20 +0000106#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000107#define USB_STOR_TRANSPORT_FAILED -1
108#define USB_STOR_TRANSPORT_ERROR -2
109
Michael Trimarchi956a4352008-12-10 15:52:06 +0100110int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glasse3394752016-02-29 15:25:34 -0700111 struct blk_desc *dev_desc);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100112int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
113 struct us_data *ss);
Simon Glass01f5be92016-02-29 15:25:58 -0700114#ifdef CONFIG_BLK
115static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
116 lbaint_t blkcnt, void *buffer);
117static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
118 lbaint_t blkcnt, const void *buffer);
119#else
Simon Glasse3394752016-02-29 15:25:34 -0700120static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700121 lbaint_t blkcnt, void *buffer);
Simon Glasse3394752016-02-29 15:25:34 -0700122static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -0700123 lbaint_t blkcnt, const void *buffer);
Simon Glass01f5be92016-02-29 15:25:58 -0700124#endif
wdenkaffae2b2002-08-17 09:36:01 +0000125void uhci_show_temp_int_td(void);
126
Kim Phillipsb052b602012-10-29 13:34:32 +0000127static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000128{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200129 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000130}
131
Michael Trimarchi956a4352008-12-10 15:52:06 +0100132/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200133 * show info on storage devices; 'usb start/init' must be invoked earlier
134 * as we only retrieve structures populated during devices initialization
135 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100136int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200137{
Simon Glass99e598e2016-02-29 15:25:54 -0700138 int count = 0;
Simon Glass01f5be92016-02-29 15:25:58 -0700139#ifdef CONFIG_BLK
140 struct udevice *dev;
141
142 for (blk_first_device(IF_TYPE_USB, &dev);
143 dev;
144 blk_next_device(&dev)) {
145 struct blk_desc *desc = dev_get_uclass_platdata(dev);
146
147 printf(" Device %d: ", desc->devnum);
148 dev_print(desc);
149 count++;
150 }
151#else
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200152 int i;
153
Aras Vaichas7ede1862008-03-25 12:09:07 +1100154 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200155 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100156 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200157 dev_print(&usb_dev_desc[i]);
158 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100159 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100160 }
Simon Glass01f5be92016-02-29 15:25:58 -0700161#endif
Simon Glass99e598e2016-02-29 15:25:54 -0700162 if (!count) {
163 printf("No storage devices, perhaps not 'usb start'ed..?\n");
164 return 1;
165 }
166
Simon Glass8c6c0742016-03-16 07:45:44 -0600167 return 0;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200168}
169
Ludovic Courtès134396c2010-10-05 22:04:26 +0200170static unsigned int usb_get_max_lun(struct us_data *us)
171{
172 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530173 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200174 len = usb_control_msg(us->pusb_dev,
175 usb_rcvctrlpipe(us->pusb_dev, 0),
176 US_BBB_GET_MAX_LUN,
177 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
178 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530179 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200180 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530181 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530182 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200183}
184
Simon Glass99e598e2016-02-29 15:25:54 -0700185static int usb_stor_probe_device(struct usb_device *udev)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600186{
Simon Glass99e598e2016-02-29 15:25:54 -0700187 int lun, max_lun;
Simon Glass01f5be92016-02-29 15:25:58 -0700188
189#ifdef CONFIG_BLK
190 struct us_data *data;
Simon Glass01f5be92016-02-29 15:25:58 -0700191 int ret;
192#else
Simon Glass99e598e2016-02-29 15:25:54 -0700193 int start;
194
195 if (udev == NULL)
Simon Glassdf7d34f2015-03-25 12:22:15 -0600196 return -ENOENT; /* no more devices available */
Simon Glass01f5be92016-02-29 15:25:58 -0700197#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600198
Simon Glass01f5be92016-02-29 15:25:58 -0700199 debug("\n\nProbing for storage\n");
200#ifdef CONFIG_BLK
201 /*
202 * We store the us_data in the mass storage device's platdata. It
203 * is shared by all LUNs (block devices) attached to this mass storage
204 * device.
205 */
206 data = dev_get_platdata(udev->dev);
207 if (!usb_storage_probe(udev, 0, data))
208 return 0;
209 max_lun = usb_get_max_lun(data);
210 for (lun = 0; lun <= max_lun; lun++) {
211 struct blk_desc *blkdev;
212 struct udevice *dev;
Simon Glass966b6952016-05-01 11:36:29 -0600213 char str[10];
Simon Glass01f5be92016-02-29 15:25:58 -0700214
Simon Glass966b6952016-05-01 11:36:29 -0600215 snprintf(str, sizeof(str), "lun%d", lun);
216 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
217 IF_TYPE_USB, usb_max_devs, 512, 0,
218 &dev);
Simon Glass01f5be92016-02-29 15:25:58 -0700219 if (ret) {
220 debug("Cannot bind driver\n");
221 return ret;
222 }
223
224 blkdev = dev_get_uclass_platdata(dev);
225 blkdev->target = 0xff;
226 blkdev->lun = lun;
227
228 ret = usb_stor_get_info(udev, data, blkdev);
229 if (ret == 1)
230 ret = blk_prepare_device(dev);
231 if (!ret) {
232 usb_max_devs++;
233 debug("%s: Found device %p\n", __func__, udev);
234 } else {
235 debug("usb_stor_get_info: Invalid device\n");
236 ret = device_unbind(dev);
237 if (ret)
238 return ret;
239 }
240 }
241#else
Simon Glass6d74d7c2016-02-29 15:25:53 -0700242 /* We don't have space to even probe if we hit the maximum */
243 if (usb_max_devs == USB_MAX_STOR_DEV) {
244 printf("max USB Storage Device reached: %d stopping\n",
245 usb_max_devs);
246 return -ENOSPC;
247 }
248
Simon Glass99e598e2016-02-29 15:25:54 -0700249 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
250 return 0;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600251
Simon Glass99e598e2016-02-29 15:25:54 -0700252 /*
253 * OK, it's a storage device. Iterate over its LUNs and populate
254 * usb_dev_desc'
255 */
256 start = usb_max_devs;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600257
Simon Glass99e598e2016-02-29 15:25:54 -0700258 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
259 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
260 lun++) {
261 struct blk_desc *blkdev;
Simon Glassdf7d34f2015-03-25 12:22:15 -0600262
Simon Glass99e598e2016-02-29 15:25:54 -0700263 blkdev = &usb_dev_desc[usb_max_devs];
264 memset(blkdev, '\0', sizeof(struct blk_desc));
265 blkdev->if_type = IF_TYPE_USB;
266 blkdev->devnum = usb_max_devs;
267 blkdev->part_type = PART_TYPE_UNKNOWN;
268 blkdev->target = 0xff;
269 blkdev->type = DEV_TYPE_UNKNOWN;
270 blkdev->block_read = usb_stor_read;
271 blkdev->block_write = usb_stor_write;
272 blkdev->lun = lun;
273 blkdev->priv = udev;
274
275 if (usb_stor_get_info(udev, &usb_stor[start],
276 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass01f5be92016-02-29 15:25:58 -0700277 debug("partype: %d\n", blkdev->part_type);
278 part_init(blkdev);
279 debug("partype: %d\n", blkdev->part_type);
Simon Glass99e598e2016-02-29 15:25:54 -0700280 usb_max_devs++;
281 debug("%s: Found device %p\n", __func__, udev);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600282 }
283 }
Simon Glass01f5be92016-02-29 15:25:58 -0700284#endif
Simon Glassdf7d34f2015-03-25 12:22:15 -0600285
Simon Glassdf7d34f2015-03-25 12:22:15 -0600286 return 0;
287}
288
289void usb_stor_reset(void)
290{
291 usb_max_devs = 0;
292}
293
Michael Trimarchi956a4352008-12-10 15:52:06 +0100294/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200295 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000296 * to the user if mode = 1
297 * returns current device or -1 if no
298 */
299int usb_stor_scan(int mode)
300{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100301 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200302 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100303
Michal Simekcd8f86f2016-12-21 09:35:08 +0100304#ifndef CONFIG_DM_USB
305 unsigned char i;
306
wdenkaffae2b2002-08-17 09:36:01 +0000307 usb_disable_asynch(1); /* asynch transfer not allowed */
308
Simon Glassdf7d34f2015-03-25 12:22:15 -0600309 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100310 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600311 struct usb_device *dev;
312
Michael Trimarchi956a4352008-12-10 15:52:06 +0100313 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530314 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600315 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000316 break;
wdenkaffae2b2002-08-17 09:36:01 +0000317 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200318
wdenkaffae2b2002-08-17 09:36:01 +0000319 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekcd8f86f2016-12-21 09:35:08 +0100320#endif
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200321 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100322 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000323 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100324 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000325}
326
327static int usb_stor_irq(struct usb_device *dev)
328{
329 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100330 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000331
Michael Trimarchi956a4352008-12-10 15:52:06 +0100332 if (us->ip_wanted)
333 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
335}
336
337
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530338#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000339
Simon Glass5fb559d2017-06-14 21:28:30 -0600340static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000341{
342 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100343 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
344 for (i = 0; i < 12; i++)
345 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000346 printf("\n");
347}
348
349static void display_int_status(unsigned long tmp)
350{
351 printf("Status: %s %s %s %s %s %s %s\n",
352 (tmp & USB_ST_ACTIVE) ? "Active" : "",
353 (tmp & USB_ST_STALLED) ? "Stalled" : "",
354 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
355 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
356 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
357 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
358 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
359}
360#endif
361/***********************************************************************
362 * Data transfer routines
363 ***********************************************************************/
364
365static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
366{
367 int max_size;
368 int this_xfer;
369 int result;
370 int partial;
371 int maxtry;
372 int stat;
373
374 /* determine the maximum packet size for these transfers */
375 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
376
377 /* while we have data left to transfer */
378 while (length) {
379
380 /* calculate how long this will be -- maximum or a remainder */
381 this_xfer = length > max_size ? max_size : length;
382 length -= this_xfer;
383
384 /* setup the retry counter */
385 maxtry = 10;
386
387 /* set up the transfer loop */
388 do {
389 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600390 debug("Bulk xfer 0x%lx(%d) try #%d\n",
391 (ulong)map_to_sysmem(buf), this_xfer,
392 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000393 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100394 this_xfer, &partial,
395 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530396 debug("bulk_msg returned %d xferred %d/%d\n",
397 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100398 if (us->pusb_dev->status != 0) {
399 /* if we stall, we need to clear it before
400 * we go on
401 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530402#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000403 display_int_status(us->pusb_dev->status);
404#endif
405 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530406 debug("stalled ->clearing endpoint" \
407 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000408 stat = us->pusb_dev->status;
409 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100410 us->pusb_dev->status = stat;
411 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530412 debug("bulk transferred" \
413 "with error %lX," \
414 " but data ok\n",
415 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000416 return 0;
417 }
418 else
419 return result;
420 }
421 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530422 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000423 return result;
424 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530425 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100426 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530427 debug(" %ld, but data ok\n",
428 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000429 return 0;
430 }
431 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530432 debug(" %ld, data %d\n",
433 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000434 if (!maxtry--)
435 return result;
436 }
437 /* update to show what data was transferred */
438 this_xfer -= partial;
439 buf += partial;
440 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100441 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000442 }
443
444 /* if we get here, we're done and successful */
445 return 0;
446}
447
wdenkde887eb2003-09-10 18:20:28 +0000448static int usb_stor_BBB_reset(struct us_data *us)
449{
450 int result;
451 unsigned int pipe;
452
453 /*
454 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
455 *
456 * For Reset Recovery the host shall issue in the following order:
457 * a) a Bulk-Only Mass Storage Reset
458 * b) a Clear Feature HALT to the Bulk-In endpoint
459 * c) a Clear Feature HALT to the Bulk-Out endpoint
460 *
461 * This is done in 3 steps.
462 *
463 * If the reset doesn't succeed, the device should be port reset.
464 *
465 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
466 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530467 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100468 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
469 US_BBB_RESET,
470 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000471 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200472
Michael Trimarchi956a4352008-12-10 15:52:06 +0100473 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530474 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000475 return -1;
476 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200477
wdenkde887eb2003-09-10 18:20:28 +0000478 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000479 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530480 debug("BBB_reset result %d: status %lX reset\n",
481 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000482 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
483 result = usb_clear_halt(us->pusb_dev, pipe);
484 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000485 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530486 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
487 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000488 /* long wait for reset */
489 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
490 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
493 result, us->pusb_dev->status);
494 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000495 return 0;
496}
497
wdenkaffae2b2002-08-17 09:36:01 +0000498/* FIXME: this reset function doesn't really reset the port, and it
499 * should. Actually it should probably do what it's doing here, and
500 * reset the port physically
501 */
502static int usb_stor_CB_reset(struct us_data *us)
503{
504 unsigned char cmd[12];
505 int result;
506
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530507 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100508 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000509 cmd[0] = SCSI_SEND_DIAG;
510 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100511 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
512 US_CBI_ADSC,
513 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
514 0, us->ifnum, cmd, sizeof(cmd),
515 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000516
517 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000518 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530519 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
520 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000521 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
522 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
523
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530524 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000525 return 0;
526}
527
wdenkde887eb2003-09-10 18:20:28 +0000528/*
529 * Set up the command for a BBB device. Note that the actual SCSI
530 * command is copied into cbw.CBWCDB.
531 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600532static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000533{
534 int result;
535 int actlen;
536 int dir_in;
537 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600538 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000539
540 dir_in = US_DIRECTION(srb->cmd[0]);
541
542#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530543 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100544 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
545 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000546 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100547 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000548 printf("cmd[%d] %#x ", result, srb->cmd[result]);
549 printf("\n");
550 }
551#endif
552 /* sanity checks */
553 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530554 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000555 return -1;
556 }
557
558 /* always OUT to the ep */
559 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
560
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530561 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
562 cbw->dCBWTag = cpu_to_le32(CBWTag++);
563 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
564 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
565 cbw->bCBWLUN = srb->lun;
566 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000567 /* copy the command data into the CBW command data buffer */
568 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300569
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530570 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
571 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100572 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000573 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530574 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000575 return result;
576}
577
wdenkaffae2b2002-08-17 09:36:01 +0000578/* FIXME: we also need a CBI_command which sets up the completion
579 * interrupt, and waits for it
580 */
Simon Glass5fb559d2017-06-14 21:28:30 -0600581static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000582{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200583 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100584 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000585 unsigned int pipe;
586 unsigned long status;
587
Michael Trimarchi956a4352008-12-10 15:52:06 +0100588 retry = 5;
589 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000590
Michael Trimarchi956a4352008-12-10 15:52:06 +0100591 if (dir_in)
592 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
593 else
594 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
595
596 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530597 debug("CBI gets a command: Try %d\n", 5 - retry);
598#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000599 usb_show_srb(srb);
600#endif
601 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100602 result = usb_control_msg(us->pusb_dev,
603 usb_sndctrlpipe(us->pusb_dev , 0),
604 US_CBI_ADSC,
605 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000606 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100607 srb->cmd, srb->cmdlen,
608 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530609 debug("CB_transport: control msg returned %d, status %lX\n",
610 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000611 /* check the return code for the command */
612 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100613 if (us->pusb_dev->status & USB_ST_STALLED) {
614 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530615 debug(" stall during command found," \
616 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100617 usb_clear_halt(us->pusb_dev,
618 usb_sndctrlpipe(us->pusb_dev, 0));
619 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000620 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530621 debug(" error during command %02X" \
622 " Stat = %lX\n", srb->cmd[0],
623 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000624 return result;
625 }
626 /* transfer the data payload for this command, if one exists*/
627
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530628 debug("CB_transport: control msg returned %d," \
629 " direction is %s to go 0x%lx\n", result,
630 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000631 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100632 result = us_one_transfer(us, pipe, (char *)srb->pdata,
633 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530634 debug("CBI attempted to transfer data," \
635 " result is %d status %lX, len %d\n",
636 result, us->pusb_dev->status,
637 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100638 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000639 break;
640 } /* if (srb->datalen) */
641 else
642 break;
643 }
644 /* return result */
645
646 return result;
647}
648
649
Simon Glass5fb559d2017-06-14 21:28:30 -0600650static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000651{
652 int timeout;
653
wdenk5f495752004-02-26 23:46:20 +0000654 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100655 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000656 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
657 timeout = 1000;
658 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300659 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000660 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000661 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000662 }
663 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100664 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000665 us->ip_wanted = 0;
666 return USB_STOR_TRANSPORT_ERROR;
667 }
Vagrant Cascadian53d41e62016-03-15 12:16:39 -0700668 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530669 us->ip_data, us->pusb_dev->irq_act_len,
670 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000671 /* UFI gives us ASC and ASCQ, like a request sense */
672 if (us->subclass == US_SC_UFI) {
673 if (srb->cmd[0] == SCSI_REQ_SENSE ||
674 srb->cmd[0] == SCSI_INQUIRY)
675 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000676 else if (us->ip_data)
677 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000678 else
wdenk5f495752004-02-26 23:46:20 +0000679 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000680 }
681 /* otherwise, we interpret the data normally */
682 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000683 case 0x0001:
684 return USB_STOR_TRANSPORT_GOOD;
685 case 0x0002:
686 return USB_STOR_TRANSPORT_FAILED;
687 default:
688 return USB_STOR_TRANSPORT_ERROR;
689 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000690 return USB_STOR_TRANSPORT_ERROR;
691}
692
693#define USB_TRANSPORT_UNKNOWN_RETRY 5
694#define USB_TRANSPORT_NOT_READY_RETRY 10
695
wdenkde887eb2003-09-10 18:20:28 +0000696/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000697static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000698{
wdenkde887eb2003-09-10 18:20:28 +0000699 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada9b70df52016-09-06 22:17:35 +0900700 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
701 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
702 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000703}
704
Simon Glass5fb559d2017-06-14 21:28:30 -0600705static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000706{
707 int result, retry;
708 int dir_in;
709 int actlen, data_actlen;
710 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600711 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000712#ifdef BBB_XPORT_TRACE
713 unsigned char *ptr;
714 int index;
715#endif
716
717 dir_in = US_DIRECTION(srb->cmd[0]);
718
719 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530720 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000721 result = usb_stor_BBB_comdat(srb, us);
722 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530723 debug("failed to send CBW status %ld\n",
724 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
727 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200728 if (!(us->flags & USB_READY))
729 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000730 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
731 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
732 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000733 data_actlen = 0;
734 /* no data, go immediately to the STATUS phase */
735 if (srb->datalen == 0)
736 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530737 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000738 if (dir_in)
739 pipe = pipein;
740 else
741 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300742
Michael Trimarchi956a4352008-12-10 15:52:06 +0100743 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
744 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000745 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100746 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530747 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000748 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100749 result = usb_stor_BBB_clear_endpt_stall(us,
750 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000751 if (result >= 0)
752 /* continue on to STATUS phase */
753 goto st;
754 }
755 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530756 debug("usb_bulk_msg error status %ld\n",
757 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000758 usb_stor_BBB_reset(us);
759 return USB_STOR_TRANSPORT_FAILED;
760 }
761#ifdef BBB_XPORT_TRACE
762 for (index = 0; index < data_actlen; index++)
763 printf("pdata[%d] %#x ", index, srb->pdata[index]);
764 printf("\n");
765#endif
766 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100767st:
wdenkde887eb2003-09-10 18:20:28 +0000768 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100769again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530770 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530771 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200772 &actlen, USB_CNTL_TIMEOUT*5);
773
wdenkde887eb2003-09-10 18:20:28 +0000774 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100775 if ((result < 0) && (retry < 1) &&
776 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530777 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000778 /* clear the STALL on the endpoint */
779 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
780 if (result >= 0 && (retry++ < 1))
781 /* do a retry */
782 goto again;
783 }
784 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530785 debug("usb_bulk_msg error status %ld\n",
786 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000787 usb_stor_BBB_reset(us);
788 return USB_STOR_TRANSPORT_FAILED;
789 }
790#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530791 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000792 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
793 printf("ptr[%d] %#x ", index, ptr[index]);
794 printf("\n");
795#endif
796 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530797 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000798 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
799 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530800 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530801 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000802 usb_stor_BBB_reset(us);
803 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530804 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530805 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000806 usb_stor_BBB_reset(us);
807 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530808 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530809 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000810 usb_stor_BBB_reset(us);
811 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530812 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530813 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000814 usb_stor_BBB_reset(us);
815 return USB_STOR_TRANSPORT_FAILED;
816 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530817 debug("transferred %dB instead of %ldB\n",
818 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000819 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530820 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530821 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000822 return USB_STOR_TRANSPORT_FAILED;
823 }
824
825 return result;
826}
827
Simon Glass5fb559d2017-06-14 21:28:30 -0600828static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000829{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100830 int result, status;
Simon Glass5fb559d2017-06-14 21:28:30 -0600831 struct scsi_cmd *psrb;
832 struct scsi_cmd reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100833 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000834
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200835 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100836 status = USB_STOR_TRANSPORT_GOOD;
837 retry = 0;
838 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000839 /* issue the command */
840do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100841 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530842 debug("command / Data returned %d, status %lX\n",
843 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 if (us->protocol == US_PR_CBI) {
846 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530849 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000850 return status;
851 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100852 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
853 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
854 if (!us->ip_data) {
855 /* if the status is good, report it */
856 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530857 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000858 return status;
859 }
860 }
861 }
862 /* do we have to issue an auto request? */
863 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100864 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530865 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000866 us->transport_reset(us);
867 return USB_STOR_TRANSPORT_ERROR;
868 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100869 if ((us->protocol == US_PR_CBI) &&
870 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
871 (srb->cmd[0] == SCSI_INQUIRY))) {
872 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530873 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000874 return USB_STOR_TRANSPORT_GOOD;
875 }
876 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100877 memset(&psrb->cmd[0], 0, 12);
878 psrb->cmd[0] = SCSI_REQ_SENSE;
879 psrb->cmd[1] = srb->lun << 5;
880 psrb->cmd[4] = 18;
881 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200882 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100883 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000884 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100885 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530886 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000887 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100888 if (us->protocol == US_PR_CBI)
889 status = usb_stor_CBI_get_status(psrb, us);
890
891 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530892 debug(" AUTO REQUEST ERROR %ld\n",
893 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000894 return USB_STOR_TRANSPORT_ERROR;
895 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530896 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
897 srb->sense_buf[0], srb->sense_buf[2],
898 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000899 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100900 if ((srb->sense_buf[2] == 0) &&
901 (srb->sense_buf[12] == 0) &&
902 (srb->sense_buf[13] == 0)) {
903 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000904 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100905 }
906
wdenkaffae2b2002-08-17 09:36:01 +0000907 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100908 switch (srb->sense_buf[2]) {
909 case 0x01:
910 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000911 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000912 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100913 case 0x02:
914 /* Not Ready */
915 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
916 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
917 " 0x%02X (NOT READY)\n", srb->cmd[0],
918 srb->sense_buf[0], srb->sense_buf[2],
919 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000920 return USB_STOR_TRANSPORT_FAILED;
921 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000922 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000923 goto do_retry;
924 }
925 break;
926 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100927 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
928 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
929 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
930 srb->sense_buf[2], srb->sense_buf[12],
931 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000932 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100933 } else
wdenkde887eb2003-09-10 18:20:28 +0000934 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000935 break;
wdenkaffae2b2002-08-17 09:36:01 +0000936 }
937 return USB_STOR_TRANSPORT_FAILED;
938}
939
Bin Meng9f447112017-09-07 06:13:21 -0700940static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
941 struct us_data *us)
Bin Mengf6e373e2017-09-07 06:13:20 -0700942{
943 unsigned short blk;
Bin Meng9f447112017-09-07 06:13:21 -0700944 size_t __maybe_unused size;
945 int __maybe_unused ret;
Bin Mengf6e373e2017-09-07 06:13:20 -0700946
Bin Meng9f447112017-09-07 06:13:21 -0700947#ifndef CONFIG_DM_USB
Bin Mengf6e373e2017-09-07 06:13:20 -0700948#ifdef CONFIG_USB_EHCI_HCD
949 /*
950 * The U-Boot EHCI driver can handle any transfer length as long as
951 * there is enough free heap space left, but the SCSI READ(10) and
952 * WRITE(10) commands are limited to 65535 blocks.
953 */
954 blk = USHRT_MAX;
955#else
956 blk = 20;
957#endif
Bin Meng9f447112017-09-07 06:13:21 -0700958#else
959 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
960 if (ret < 0) {
961 /* unimplemented, let's use default 20 */
962 blk = 20;
963 } else {
964 if (size > USHRT_MAX * 512)
Bin Meng77f871b2017-09-27 21:50:07 -0700965 size = USHRT_MAX * 512;
Bin Meng9f447112017-09-07 06:13:21 -0700966 blk = size / 512;
967 }
968#endif
Bin Mengf6e373e2017-09-07 06:13:20 -0700969
970 us->max_xfer_blk = blk;
971}
wdenkaffae2b2002-08-17 09:36:01 +0000972
Simon Glass5fb559d2017-06-14 21:28:30 -0600973static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000974{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100975 int retry, i;
976 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000977 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978 memset(&srb->cmd[0], 0, 12);
979 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200980 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 srb->cmd[4] = 36;
982 srb->datalen = 36;
983 srb->cmdlen = 12;
984 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530985 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100986 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000987 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200988 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000989
Michael Trimarchi956a4352008-12-10 15:52:06 +0100990 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000991 printf("error in inquiry\n");
992 return -1;
993 }
994 return 0;
995}
996
Simon Glass5fb559d2017-06-14 21:28:30 -0600997static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000998{
999 char *ptr;
wdenk5f495752004-02-26 23:46:20 +00001000
Michael Trimarchi956a4352008-12-10 15:52:06 +01001001 ptr = (char *)srb->pdata;
1002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001005 srb->cmd[4] = 18;
1006 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +02001007 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 srb->cmdlen = 12;
1009 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301010 debug("Request Sense returned %02X %02X %02X\n",
1011 srb->sense_buf[2], srb->sense_buf[12],
1012 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001013 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001014 return 0;
1015}
1016
Simon Glass5fb559d2017-06-14 21:28:30 -06001017static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001018{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001019 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +00001020
wdenkaffae2b2002-08-17 09:36:01 +00001021 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001022 memset(&srb->cmd[0], 0, 12);
1023 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001024 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001025 srb->datalen = 0;
1026 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001027 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1028 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001029 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001030 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -08001032 /*
1033 * Check the Key Code Qualifier, if it matches
1034 * "Not Ready - medium not present"
1035 * (the sense Key equals 0x2 and the ASC is 0x3a)
1036 * return immediately as the medium being absent won't change
1037 * unless there is a user action.
1038 */
1039 if ((srb->sense_buf[2] == 0x02) &&
1040 (srb->sense_buf[12] == 0x3a))
1041 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +00001042 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001043 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +00001044
wdenkaffae2b2002-08-17 09:36:01 +00001045 return -1;
1046}
1047
Simon Glass5fb559d2017-06-14 21:28:30 -06001048static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001049{
1050 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001051 /* XXX retries */
1052 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001053 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001054 memset(&srb->cmd[0], 0, 12);
1055 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001056 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001057 srb->datalen = 8;
1058 srb->cmdlen = 12;
1059 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001060 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001061 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +00001062
wdenkaffae2b2002-08-17 09:36:01 +00001063 return -1;
1064}
1065
Simon Glass5fb559d2017-06-14 21:28:30 -06001066static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1067 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001068{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 memset(&srb->cmd[0], 0, 12);
1070 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001071 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1073 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1074 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1075 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1076 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1077 srb->cmd[8] = (unsigned char) blocks & 0xff;
1078 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301079 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001081}
1082
Simon Glass5fb559d2017-06-14 21:28:30 -06001083static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1084 unsigned long start, unsigned short blocks)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301085{
1086 memset(&srb->cmd[0], 0, 12);
1087 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001088 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301089 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1090 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1091 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1092 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1093 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1094 srb->cmd[8] = (unsigned char) blocks & 0xff;
1095 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301096 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301097 return ss->transport(srb, ss);
1098}
1099
wdenkaffae2b2002-08-17 09:36:01 +00001100
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001101#ifdef CONFIG_USB_BIN_FIXUP
1102/*
1103 * Some USB storage devices queried for SCSI identification data respond with
1104 * binary strings, which if output to the console freeze the terminal. The
1105 * workaround is to modify the vendor and product strings read from such
1106 * device with proper values (as reported by 'usb info').
1107 *
1108 * Vendor and product length limits are taken from the definition of
Simon Glasse3394752016-02-29 15:25:34 -07001109 * struct blk_desc in include/part.h.
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001110 */
1111static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1112 unsigned char vendor[],
1113 unsigned char product[]) {
1114 const unsigned char max_vendor_len = 40;
1115 const unsigned char max_product_len = 20;
1116 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001117 strncpy((char *)vendor, "SMSC", max_vendor_len);
1118 strncpy((char *)product, "Flash Media Cntrller",
1119 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001120 }
1121}
1122#endif /* CONFIG_USB_BIN_FIXUP */
1123
Simon Glass01f5be92016-02-29 15:25:58 -07001124#ifdef CONFIG_BLK
1125static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1126 lbaint_t blkcnt, void *buffer)
1127#else
Simon Glasse3394752016-02-29 15:25:34 -07001128static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001129 lbaint_t blkcnt, void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001130#endif
wdenkaffae2b2002-08-17 09:36:01 +00001131{
Gabe Black7d077682012-10-12 14:26:07 +00001132 lbaint_t start, blks;
1133 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001134 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001135 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001136 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001137 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001138 struct scsi_cmd *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001139#ifdef CONFIG_BLK
1140 struct blk_desc *block_dev;
1141#endif
wdenk0e2874cb2004-03-02 14:05:39 +00001142
1143 if (blkcnt == 0)
1144 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001145 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001146#ifdef CONFIG_BLK
1147 block_dev = dev_get_uclass_platdata(dev);
1148 udev = dev_get_parent_priv(dev_get_parent(dev));
1149 debug("\nusb_read: udev %d\n", block_dev->devnum);
1150#else
Simon Glass99e598e2016-02-29 15:25:54 -07001151 debug("\nusb_read: udev %d\n", block_dev->devnum);
1152 udev = usb_dev_desc[block_dev->devnum].priv;
1153 if (!udev) {
Simon Glass5c3c91c2015-03-25 12:22:13 -06001154 debug("%s: No device\n", __func__);
1155 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001156 }
Simon Glass01f5be92016-02-29 15:25:58 -07001157#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001158 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001159
1160 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass99e598e2016-02-29 15:25:54 -07001161 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001162 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001163 start = blknr;
1164 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001165
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001166 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1167 block_dev->devnum, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001168
wdenkaffae2b2002-08-17 09:36:01 +00001169 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001170 /* XXX need some comment here */
1171 retry = 2;
1172 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001173 if (blks > ss->max_xfer_blk)
1174 smallblks = ss->max_xfer_blk;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001175 else
1176 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001177retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001178 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001179 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001180 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001181 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001182 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301183 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001184 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001185 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001186 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001187 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001188 break;
1189 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001190 start += smallblks;
1191 blks -= smallblks;
1192 buf_addr += srb->datalen;
1193 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001194 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001195
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001196 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301197 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001198
wdenkaffae2b2002-08-17 09:36:01 +00001199 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001200 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001201 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001202 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001203}
1204
Simon Glass01f5be92016-02-29 15:25:58 -07001205#ifdef CONFIG_BLK
1206static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1207 lbaint_t blkcnt, const void *buffer)
1208#else
Simon Glasse3394752016-02-29 15:25:34 -07001209static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warrene73f2962015-12-07 11:38:48 -07001210 lbaint_t blkcnt, const void *buffer)
Simon Glass01f5be92016-02-29 15:25:58 -07001211#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301212{
Gabe Black7d077682012-10-12 14:26:07 +00001213 lbaint_t start, blks;
1214 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301215 unsigned short smallblks;
Simon Glass99e598e2016-02-29 15:25:54 -07001216 struct usb_device *udev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001217 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001218 int retry;
Simon Glass5fb559d2017-06-14 21:28:30 -06001219 struct scsi_cmd *srb = &usb_ccb;
Simon Glass01f5be92016-02-29 15:25:58 -07001220#ifdef CONFIG_BLK
1221 struct blk_desc *block_dev;
1222#endif
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301223
1224 if (blkcnt == 0)
1225 return 0;
1226
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301227 /* Setup device */
Simon Glass01f5be92016-02-29 15:25:58 -07001228#ifdef CONFIG_BLK
1229 block_dev = dev_get_uclass_platdata(dev);
1230 udev = dev_get_parent_priv(dev_get_parent(dev));
1231 debug("\nusb_read: udev %d\n", block_dev->devnum);
1232#else
Simon Glass99e598e2016-02-29 15:25:54 -07001233 debug("\nusb_read: udev %d\n", block_dev->devnum);
1234 udev = usb_dev_desc[block_dev->devnum].priv;
1235 if (!udev) {
1236 debug("%s: No device\n", __func__);
Simon Glass5c3c91c2015-03-25 12:22:13 -06001237 return 0;
Simon Glass99e598e2016-02-29 15:25:54 -07001238 }
Simon Glass01f5be92016-02-29 15:25:58 -07001239#endif
Simon Glass99e598e2016-02-29 15:25:54 -07001240 ss = (struct us_data *)udev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301241
1242 usb_disable_asynch(1); /* asynch transfer not allowed */
1243
Simon Glass99e598e2016-02-29 15:25:54 -07001244 srb->lun = block_dev->lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001245 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301246 start = blknr;
1247 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301248
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001249 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
1250 block_dev->devnum, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301251
1252 do {
1253 /* If write fails retry for max retry count else
1254 * return with number of blocks written successfully.
1255 */
1256 retry = 2;
1257 srb->pdata = (unsigned char *)buf_addr;
Bin Mengf6e373e2017-09-07 06:13:20 -07001258 if (blks > ss->max_xfer_blk)
1259 smallblks = ss->max_xfer_blk;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301260 else
1261 smallblks = (unsigned short) blks;
1262retry_it:
Bin Mengf6e373e2017-09-07 06:13:20 -07001263 if (smallblks == ss->max_xfer_blk)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301264 usb_show_progress();
Simon Glass99e598e2016-02-29 15:25:54 -07001265 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301266 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001267 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301268 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001269 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-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);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001279 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301280
Masahiro Yamadac7570a32018-08-06 20:47:40 +09001281 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1282 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301283
1284 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Mengf6e373e2017-09-07 06:13:20 -07001285 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001286 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301287 return blkcnt;
1288
1289}
wdenkaffae2b2002-08-17 09:36:01 +00001290
1291/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001292int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1293 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001294{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001295 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001296 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301297 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001298 unsigned int flags = 0;
1299
wdenkaffae2b2002-08-17 09:36:01 +00001300 /* let's examine the device now */
1301 iface = &dev->config.if_desc[ifnum];
1302
wdenkaffae2b2002-08-17 09:36:01 +00001303 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001304 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1305 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1306 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001307 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001308 /* if it's not a mass storage, we go no further */
1309 return 0;
1310 }
1311
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001312 memset(ss, 0, sizeof(struct us_data));
1313
wdenkaffae2b2002-08-17 09:36:01 +00001314 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301315 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001316
1317 /* Initialize the us_data structure with some useful info */
1318 ss->flags = flags;
1319 ss->ifnum = ifnum;
1320 ss->pusb_dev = dev;
1321 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001322 ss->subclass = iface->desc.bInterfaceSubClass;
1323 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001324
1325 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301326 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001327 switch (ss->protocol) {
1328 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301329 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001330 ss->transport = usb_stor_CB_transport;
1331 ss->transport_reset = usb_stor_CB_reset;
1332 break;
1333
1334 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301335 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001336 ss->transport = usb_stor_CB_transport;
1337 ss->transport_reset = usb_stor_CB_reset;
1338 break;
wdenkde887eb2003-09-10 18:20:28 +00001339 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301340 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001341 ss->transport = usb_stor_BBB_transport;
1342 ss->transport_reset = usb_stor_BBB_reset;
1343 break;
wdenkaffae2b2002-08-17 09:36:01 +00001344 default:
wdenk5f495752004-02-26 23:46:20 +00001345 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001346 return 0;
1347 break;
1348 }
1349
1350 /*
1351 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1352 * An optional interrupt is OK (necessary for CBI protocol).
1353 * We will ignore any others.
1354 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001355 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301356 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001357 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301358 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001359 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301360 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1361 ss->ep_in = ep_desc->bEndpointAddress &
1362 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001363 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001364 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301365 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001366 USB_ENDPOINT_NUMBER_MASK;
1367 }
1368
1369 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301370 if ((ep_desc->bmAttributes &
1371 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1372 ss->ep_int = ep_desc->bEndpointAddress &
1373 USB_ENDPOINT_NUMBER_MASK;
1374 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001375 }
1376 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301377 debug("Endpoints In %d Out %d Int %d\n",
1378 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001379
1380 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001381 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001382 !ss->ep_in || !ss->ep_out ||
1383 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301384 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001385 return 0;
1386 }
1387 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001388 /* We only handle certain protocols. Currently, these are
1389 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001390 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001391 */
wdenk5f495752004-02-26 23:46:20 +00001392 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1393 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001394 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001395 return 0;
1396 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001397 if (ss->ep_int) {
1398 /* we had found an interrupt endpoint, prepare irq pipe
1399 * set up the IRQ pipe and handler
1400 */
wdenkaffae2b2002-08-17 09:36:01 +00001401 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1402 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1403 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001404 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001405 }
Bin Mengf6e373e2017-09-07 06:13:20 -07001406
1407 /* Set the maximum transfer size per host controller setting */
Bin Meng9f447112017-09-07 06:13:21 -07001408 usb_stor_set_max_xfer_blk(dev, ss);
Bin Mengf6e373e2017-09-07 06:13:20 -07001409
Michael Trimarchi956a4352008-12-10 15:52:06 +01001410 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001411 return 1;
1412}
1413
Michael Trimarchi956a4352008-12-10 15:52:06 +01001414int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glasse3394752016-02-29 15:25:34 -07001415 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001416{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001417 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001418 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1419 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1420 u32 capacity, blksz;
Simon Glass5fb559d2017-06-14 21:28:30 -06001421 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001422
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001423 pccb->pdata = usb_stor_buf;
1424
1425 dev_desc->target = dev->devnum;
1426 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301427 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001428
Simon Glass78330d62015-03-25 12:22:12 -06001429 if (usb_inquiry(pccb, ss)) {
1430 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001431 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001432 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001433
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001434 perq = usb_stor_buf[0];
1435 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001436
Soeren Moche4828002014-11-08 07:02:14 +01001437 /*
1438 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1439 * they would not respond to test_unit_ready .
1440 */
1441 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001442 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001443 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001444 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001445 if ((modi&0x80) == 0x80) {
1446 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001447 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001449 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1450 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1451 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001452 dev_desc->vendor[8] = 0;
1453 dev_desc->product[16] = 0;
1454 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001455#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001456 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1457 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001458#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301459 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1460 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001461 if (usb_test_unit_ready(pccb, ss)) {
1462 printf("Device NOT ready\n"
1463 " Request Sense returned %02X %02X %02X\n",
1464 pccb->sense_buf[2], pccb->sense_buf[12],
1465 pccb->sense_buf[13]);
Troy Kisky17e45262017-04-10 18:23:11 -07001466 if (dev_desc->removable == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001467 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001468 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001469 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001470 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001471 memset(pccb->pdata, 0, 8);
1472 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001473 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001474 cap[0] = 2880;
1475 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001476 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001477 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001478 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001479#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001480 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1481 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001482
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001483 cap[0] = cpu_to_be32(cap[0]);
1484 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001485#endif
1486
1487 capacity = be32_to_cpu(cap[0]) + 1;
1488 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001489
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001490 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1491 dev_desc->lba = capacity;
1492 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001493 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001494 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301495 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001496
wdenkaffae2b2002-08-17 09:36:01 +00001497 return 1;
1498}
Simon Glassac9774e2015-03-25 12:22:16 -06001499
1500#ifdef CONFIG_DM_USB
1501
1502static int usb_mass_storage_probe(struct udevice *dev)
1503{
Simon Glassde44acf2015-09-28 23:32:01 -06001504 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001505 int ret;
1506
1507 usb_disable_asynch(1); /* asynch transfer not allowed */
1508 ret = usb_stor_probe_device(udev);
1509 usb_disable_asynch(0); /* asynch transfer allowed */
1510
1511 return ret;
1512}
1513
1514static const struct udevice_id usb_mass_storage_ids[] = {
1515 { .compatible = "usb-mass-storage" },
1516 { }
1517};
1518
1519U_BOOT_DRIVER(usb_mass_storage) = {
1520 .name = "usb_mass_storage",
1521 .id = UCLASS_MASS_STORAGE,
1522 .of_match = usb_mass_storage_ids,
1523 .probe = usb_mass_storage_probe,
Simon Glass01f5be92016-02-29 15:25:58 -07001524#ifdef CONFIG_BLK
1525 .platdata_auto_alloc_size = sizeof(struct us_data),
1526#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001527};
1528
1529UCLASS_DRIVER(usb_mass_storage) = {
1530 .id = UCLASS_MASS_STORAGE,
1531 .name = "usb_mass_storage",
1532};
1533
1534static const struct usb_device_id mass_storage_id_table[] = {
1535 {
1536 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1537 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1538 },
1539 { } /* Terminating entry */
1540};
1541
Simon Glass46952fb2015-07-06 16:47:51 -06001542U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass01f5be92016-02-29 15:25:58 -07001543#endif
Simon Glassac9774e2015-03-25 12:22:16 -06001544
Simon Glass01f5be92016-02-29 15:25:58 -07001545#ifdef CONFIG_BLK
1546static const struct blk_ops usb_storage_ops = {
1547 .read = usb_stor_read,
1548 .write = usb_stor_write,
1549};
1550
1551U_BOOT_DRIVER(usb_storage_blk) = {
1552 .name = "usb_storage_blk",
1553 .id = UCLASS_BLK,
1554 .ops = &usb_storage_ops,
1555};
Simon Glassd3171412016-05-01 11:36:06 -06001556#else
1557U_BOOT_LEGACY_BLK(usb) = {
1558 .if_typename = "usb",
1559 .if_type = IF_TYPE_USB,
1560 .max_devs = USB_MAX_STOR_DEV,
1561 .desc = usb_dev_desc,
1562};
Simon Glassac9774e2015-03-25 12:22:16 -06001563#endif