blob: d92ebb6eb19043fba3851885ea8dfc94652c50c8 [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
Simon Glass07b2b782016-02-29 15:25:58 -070069#ifndef CONFIG_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
Simon Glass07b2b782016-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 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);
Simon Glass07b2b782016-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 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;
Simon Glass07b2b782016-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 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
189#ifdef CONFIG_BLK
190 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");
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 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);
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 Glassc89e79d2016-02-29 15:25:53 -0700242 /* We don't have space to even probe if we hit the maximum */
243 if (usb_max_devs == USB_MAX_STOR_DEV) {
244 printf("max USB Storage Device reached: %d stopping\n",
245 usb_max_devs);
246 return -ENOSPC;
247 }
248
Simon Glass9807c3b2016-02-29 15:25:54 -0700249 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
250 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600251
Simon Glass9807c3b2016-02-29 15:25:54 -0700252 /*
253 * OK, it's a storage device. Iterate over its LUNs and populate
254 * usb_dev_desc'
255 */
256 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600257
Simon Glass9807c3b2016-02-29 15:25:54 -0700258 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
259 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
260 lun++) {
261 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600262
Simon Glass9807c3b2016-02-29 15:25:54 -0700263 blkdev = &usb_dev_desc[usb_max_devs];
264 memset(blkdev, '\0', sizeof(struct blk_desc));
265 blkdev->if_type = IF_TYPE_USB;
266 blkdev->devnum = usb_max_devs;
267 blkdev->part_type = PART_TYPE_UNKNOWN;
268 blkdev->target = 0xff;
269 blkdev->type = DEV_TYPE_UNKNOWN;
270 blkdev->block_read = usb_stor_read;
271 blkdev->block_write = usb_stor_write;
272 blkdev->lun = lun;
273 blkdev->priv = udev;
274
275 if (usb_stor_get_info(udev, &usb_stor[start],
276 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700277 debug("partype: %d\n", blkdev->part_type);
278 part_init(blkdev);
279 debug("partype: %d\n", blkdev->part_type);
Simon Glass9807c3b2016-02-29 15:25:54 -0700280 usb_max_devs++;
281 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600282 }
283 }
Simon Glass07b2b782016-02-29 15:25:58 -0700284#endif
Simon Glass91557572015-03-25 12:22:15 -0600285
Simon Glass91557572015-03-25 12:22:15 -0600286 return 0;
287}
288
289void usb_stor_reset(void)
290{
291 usb_max_devs = 0;
292}
293
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100294/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200295 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000296 * to the user if mode = 1
297 * returns current device or -1 if no
298 */
299int usb_stor_scan(int mode)
300{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100301 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200302 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100303
Michal Simekb9847002016-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 Glass91557572015-03-25 12:22:15 -0600309 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100310 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600311 struct usb_device *dev;
312
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100313 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530314 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600315 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000316 break;
wdenkaffae2b2002-08-17 09:36:01 +0000317 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200318
wdenkaffae2b2002-08-17 09:36:01 +0000319 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekb9847002016-12-21 09:35:08 +0100320#endif
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200321 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100322 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000323 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100324 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000325}
326
327static int usb_stor_irq(struct usb_device *dev)
328{
329 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100330 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000331
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100332 if (us->ip_wanted)
333 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
335}
336
337
Vivek Gautamceb49722013-04-12 16:34:33 +0530338#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000339
Simon Glassb9560ad2017-06-14 21:28:30 -0600340static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000341{
342 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100343 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
344 for (i = 0; i < 12; i++)
345 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000346 printf("\n");
347}
348
349static void display_int_status(unsigned long tmp)
350{
351 printf("Status: %s %s %s %s %s %s %s\n",
352 (tmp & USB_ST_ACTIVE) ? "Active" : "",
353 (tmp & USB_ST_STALLED) ? "Stalled" : "",
354 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
355 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
356 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
357 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
358 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
359}
360#endif
361/***********************************************************************
362 * Data transfer routines
363 ***********************************************************************/
364
365static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
366{
367 int max_size;
368 int this_xfer;
369 int result;
370 int partial;
371 int maxtry;
372 int stat;
373
374 /* determine the maximum packet size for these transfers */
375 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
376
377 /* while we have data left to transfer */
378 while (length) {
379
380 /* calculate how long this will be -- maximum or a remainder */
381 this_xfer = length > max_size ? max_size : length;
382 length -= this_xfer;
383
384 /* setup the retry counter */
385 maxtry = 10;
386
387 /* set up the transfer loop */
388 do {
389 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600390 debug("Bulk xfer 0x%lx(%d) try #%d\n",
391 (ulong)map_to_sysmem(buf), this_xfer,
392 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000393 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100394 this_xfer, &partial,
395 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530396 debug("bulk_msg returned %d xferred %d/%d\n",
397 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100398 if (us->pusb_dev->status != 0) {
399 /* if we stall, we need to clear it before
400 * we go on
401 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530402#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000403 display_int_status(us->pusb_dev->status);
404#endif
405 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530406 debug("stalled ->clearing endpoint" \
407 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000408 stat = us->pusb_dev->status;
409 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100410 us->pusb_dev->status = stat;
411 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530412 debug("bulk transferred" \
413 "with error %lX," \
414 " but data ok\n",
415 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000416 return 0;
417 }
418 else
419 return result;
420 }
421 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530422 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000423 return result;
424 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530425 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100426 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530427 debug(" %ld, but data ok\n",
428 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000429 return 0;
430 }
431 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530432 debug(" %ld, data %d\n",
433 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000434 if (!maxtry--)
435 return result;
436 }
437 /* update to show what data was transferred */
438 this_xfer -= partial;
439 buf += partial;
440 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100441 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000442 }
443
444 /* if we get here, we're done and successful */
445 return 0;
446}
447
wdenk149dded2003-09-10 18:20:28 +0000448static int usb_stor_BBB_reset(struct us_data *us)
449{
450 int result;
451 unsigned int pipe;
452
453 /*
454 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
455 *
456 * For Reset Recovery the host shall issue in the following order:
457 * a) a Bulk-Only Mass Storage Reset
458 * b) a Clear Feature HALT to the Bulk-In endpoint
459 * c) a Clear Feature HALT to the Bulk-Out endpoint
460 *
461 * This is done in 3 steps.
462 *
463 * If the reset doesn't succeed, the device should be port reset.
464 *
465 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
466 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530467 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100468 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
469 US_BBB_RESET,
470 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000471 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200472
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100473 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530474 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000475 return -1;
476 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200477
wdenk149dded2003-09-10 18:20:28 +0000478 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000479 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530480 debug("BBB_reset result %d: status %lX reset\n",
481 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000482 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
483 result = usb_clear_halt(us->pusb_dev, pipe);
484 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000485 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530486 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
487 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000488 /* long wait for reset */
489 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
490 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000491 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530492 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
493 result, us->pusb_dev->status);
494 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000495 return 0;
496}
497
wdenkaffae2b2002-08-17 09:36:01 +0000498/* FIXME: this reset function doesn't really reset the port, and it
499 * should. Actually it should probably do what it's doing here, and
500 * reset the port physically
501 */
502static int usb_stor_CB_reset(struct us_data *us)
503{
504 unsigned char cmd[12];
505 int result;
506
Vivek Gautamceb49722013-04-12 16:34:33 +0530507 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000509 cmd[0] = SCSI_SEND_DIAG;
510 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100511 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
512 US_CBI_ADSC,
513 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
514 0, us->ifnum, cmd, sizeof(cmd),
515 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000516
517 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000518 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530519 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
520 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000521 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
522 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
523
Vivek Gautamceb49722013-04-12 16:34:33 +0530524 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000525 return 0;
526}
527
wdenk149dded2003-09-10 18:20:28 +0000528/*
529 * Set up the command for a BBB device. Note that the actual SCSI
530 * command is copied into cbw.CBWCDB.
531 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600532static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000533{
534 int result;
535 int actlen;
536 int dir_in;
537 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600538 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000539
540 dir_in = US_DIRECTION(srb->cmd[0]);
541
542#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530543 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100544 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
545 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000546 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000548 printf("cmd[%d] %#x ", result, srb->cmd[result]);
549 printf("\n");
550 }
551#endif
552 /* sanity checks */
553 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530554 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000555 return -1;
556 }
557
558 /* always OUT to the ep */
559 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
560
Puneet Saxenaf5766132012-04-03 14:56:06 +0530561 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
562 cbw->dCBWTag = cpu_to_le32(CBWTag++);
563 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
564 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
565 cbw->bCBWLUN = srb->lun;
566 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000567 /* copy the command data into the CBW command data buffer */
568 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300569
Puneet Saxenaf5766132012-04-03 14:56:06 +0530570 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
571 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100572 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000573 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530574 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000575 return result;
576}
577
wdenkaffae2b2002-08-17 09:36:01 +0000578/* FIXME: we also need a CBI_command which sets up the completion
579 * interrupt, and waits for it
580 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600581static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000582{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200583 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100584 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000585 unsigned int pipe;
586 unsigned long status;
587
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100588 retry = 5;
589 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000590
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100591 if (dir_in)
592 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
593 else
594 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
595
596 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530597 debug("CBI gets a command: Try %d\n", 5 - retry);
598#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000599 usb_show_srb(srb);
600#endif
601 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100602 result = usb_control_msg(us->pusb_dev,
603 usb_sndctrlpipe(us->pusb_dev , 0),
604 US_CBI_ADSC,
605 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000606 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100607 srb->cmd, srb->cmdlen,
608 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530609 debug("CB_transport: control msg returned %d, status %lX\n",
610 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000611 /* check the return code for the command */
612 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100613 if (us->pusb_dev->status & USB_ST_STALLED) {
614 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530615 debug(" stall during command found," \
616 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100617 usb_clear_halt(us->pusb_dev,
618 usb_sndctrlpipe(us->pusb_dev, 0));
619 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000620 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530621 debug(" error during command %02X" \
622 " Stat = %lX\n", srb->cmd[0],
623 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000624 return result;
625 }
626 /* transfer the data payload for this command, if one exists*/
627
Vivek Gautamceb49722013-04-12 16:34:33 +0530628 debug("CB_transport: control msg returned %d," \
629 " direction is %s to go 0x%lx\n", result,
630 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000631 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100632 result = us_one_transfer(us, pipe, (char *)srb->pdata,
633 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530634 debug("CBI attempted to transfer data," \
635 " result is %d status %lX, len %d\n",
636 result, us->pusb_dev->status,
637 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100638 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000639 break;
640 } /* if (srb->datalen) */
641 else
642 break;
643 }
644 /* return result */
645
646 return result;
647}
648
649
Simon Glassb9560ad2017-06-14 21:28:30 -0600650static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000651{
652 int timeout;
653
wdenk80885a92004-02-26 23:46:20 +0000654 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100655 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000656 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
657 timeout = 1000;
658 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300659 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000660 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000661 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000662 }
663 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000665 us->ip_wanted = 0;
666 return USB_STOR_TRANSPORT_ERROR;
667 }
Vagrant Cascadiana6f70a32016-03-15 12:16:39 -0700668 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamceb49722013-04-12 16:34:33 +0530669 us->ip_data, us->pusb_dev->irq_act_len,
670 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000671 /* UFI gives us ASC and ASCQ, like a request sense */
672 if (us->subclass == US_SC_UFI) {
673 if (srb->cmd[0] == SCSI_REQ_SENSE ||
674 srb->cmd[0] == SCSI_INQUIRY)
675 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000676 else if (us->ip_data)
677 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000678 else
wdenk80885a92004-02-26 23:46:20 +0000679 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000680 }
681 /* otherwise, we interpret the data normally */
682 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000683 case 0x0001:
684 return USB_STOR_TRANSPORT_GOOD;
685 case 0x0002:
686 return USB_STOR_TRANSPORT_FAILED;
687 default:
688 return USB_STOR_TRANSPORT_ERROR;
689 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000690 return USB_STOR_TRANSPORT_ERROR;
691}
692
693#define USB_TRANSPORT_UNKNOWN_RETRY 5
694#define USB_TRANSPORT_NOT_READY_RETRY 10
695
wdenk149dded2003-09-10 18:20:28 +0000696/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000697static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000698{
wdenk149dded2003-09-10 18:20:28 +0000699 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada8319aeb2016-09-06 22:17:35 +0900700 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
701 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
702 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000703}
704
Simon Glassb9560ad2017-06-14 21:28:30 -0600705static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000706{
707 int result, retry;
708 int dir_in;
709 int actlen, data_actlen;
710 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600711 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000712#ifdef BBB_XPORT_TRACE
713 unsigned char *ptr;
714 int index;
715#endif
716
717 dir_in = US_DIRECTION(srb->cmd[0]);
718
719 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530720 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000721 result = usb_stor_BBB_comdat(srb, us);
722 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530723 debug("failed to send CBW status %ld\n",
724 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
727 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200728 if (!(us->flags & USB_READY))
729 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000730 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
731 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
732 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000733 data_actlen = 0;
734 /* no data, go immediately to the STATUS phase */
735 if (srb->datalen == 0)
736 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530737 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000738 if (dir_in)
739 pipe = pipein;
740 else
741 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300742
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100743 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
744 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000745 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100746 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530747 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000748 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100749 result = usb_stor_BBB_clear_endpt_stall(us,
750 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000751 if (result >= 0)
752 /* continue on to STATUS phase */
753 goto st;
754 }
755 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530756 debug("usb_bulk_msg error status %ld\n",
757 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000758 usb_stor_BBB_reset(us);
759 return USB_STOR_TRANSPORT_FAILED;
760 }
761#ifdef BBB_XPORT_TRACE
762 for (index = 0; index < data_actlen; index++)
763 printf("pdata[%d] %#x ", index, srb->pdata[index]);
764 printf("\n");
765#endif
766 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100767st:
wdenk149dded2003-09-10 18:20:28 +0000768 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100769again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530770 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530771 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200772 &actlen, USB_CNTL_TIMEOUT*5);
773
wdenk149dded2003-09-10 18:20:28 +0000774 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100775 if ((result < 0) && (retry < 1) &&
776 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530777 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000778 /* clear the STALL on the endpoint */
779 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
780 if (result >= 0 && (retry++ < 1))
781 /* do a retry */
782 goto again;
783 }
784 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530785 debug("usb_bulk_msg error status %ld\n",
786 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000787 usb_stor_BBB_reset(us);
788 return USB_STOR_TRANSPORT_FAILED;
789 }
790#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530791 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000792 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
793 printf("ptr[%d] %#x ", index, ptr[index]);
794 printf("\n");
795#endif
796 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530797 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000798 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
799 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530800 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530801 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000802 usb_stor_BBB_reset(us);
803 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530804 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530805 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000806 usb_stor_BBB_reset(us);
807 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530808 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530809 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000810 usb_stor_BBB_reset(us);
811 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530812 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530813 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000814 usb_stor_BBB_reset(us);
815 return USB_STOR_TRANSPORT_FAILED;
816 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530817 debug("transferred %dB instead of %ldB\n",
818 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000819 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530820 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530821 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000822 return USB_STOR_TRANSPORT_FAILED;
823 }
824
825 return result;
826}
827
Simon Glassb9560ad2017-06-14 21:28:30 -0600828static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000829{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100830 int result, status;
Simon Glassb9560ad2017-06-14 21:28:30 -0600831 struct scsi_cmd *psrb;
832 struct scsi_cmd reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100833 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000834
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200835 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100836 status = USB_STOR_TRANSPORT_GOOD;
837 retry = 0;
838 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000839 /* issue the command */
840do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100841 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530842 debug("command / Data returned %d, status %lX\n",
843 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 if (us->protocol == US_PR_CBI) {
846 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530849 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000850 return status;
851 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100852 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
853 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
854 if (!us->ip_data) {
855 /* if the status is good, report it */
856 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530857 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000858 return status;
859 }
860 }
861 }
862 /* do we have to issue an auto request? */
863 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100864 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530865 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000866 us->transport_reset(us);
867 return USB_STOR_TRANSPORT_ERROR;
868 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100869 if ((us->protocol == US_PR_CBI) &&
870 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
871 (srb->cmd[0] == SCSI_INQUIRY))) {
872 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530873 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000874 return USB_STOR_TRANSPORT_GOOD;
875 }
876 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100877 memset(&psrb->cmd[0], 0, 12);
878 psrb->cmd[0] = SCSI_REQ_SENSE;
879 psrb->cmd[1] = srb->lun << 5;
880 psrb->cmd[4] = 18;
881 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200882 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100883 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000884 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100885 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530886 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000887 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100888 if (us->protocol == US_PR_CBI)
889 status = usb_stor_CBI_get_status(psrb, us);
890
891 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530892 debug(" AUTO REQUEST ERROR %ld\n",
893 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000894 return USB_STOR_TRANSPORT_ERROR;
895 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530896 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
897 srb->sense_buf[0], srb->sense_buf[2],
898 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000899 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100900 if ((srb->sense_buf[2] == 0) &&
901 (srb->sense_buf[12] == 0) &&
902 (srb->sense_buf[13] == 0)) {
903 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000904 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100905 }
906
wdenkaffae2b2002-08-17 09:36:01 +0000907 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908 switch (srb->sense_buf[2]) {
909 case 0x01:
910 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000911 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000912 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100913 case 0x02:
914 /* Not Ready */
915 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
916 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
917 " 0x%02X (NOT READY)\n", srb->cmd[0],
918 srb->sense_buf[0], srb->sense_buf[2],
919 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000920 return USB_STOR_TRANSPORT_FAILED;
921 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000922 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000923 goto do_retry;
924 }
925 break;
926 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100927 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
928 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
929 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
930 srb->sense_buf[2], srb->sense_buf[12],
931 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000932 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100933 } else
wdenk149dded2003-09-10 18:20:28 +0000934 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000935 break;
wdenkaffae2b2002-08-17 09:36:01 +0000936 }
937 return USB_STOR_TRANSPORT_FAILED;
938}
939
Bin Mengea7fad92017-09-07 06:13:21 -0700940static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
941 struct us_data *us)
Bin Meng6158d0b2017-09-07 06:13:20 -0700942{
943 unsigned short blk;
Bin Mengea7fad92017-09-07 06:13:21 -0700944 size_t __maybe_unused size;
945 int __maybe_unused ret;
Bin Meng6158d0b2017-09-07 06:13:20 -0700946
Bin Mengea7fad92017-09-07 06:13:21 -0700947#ifndef CONFIG_DM_USB
Bin Meng6158d0b2017-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 Mengea7fad92017-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 Meng72ac8f32017-09-27 21:50:07 -0700965 size = USHRT_MAX * 512;
Bin Mengea7fad92017-09-07 06:13:21 -0700966 blk = size / 512;
967 }
968#endif
Bin Meng6158d0b2017-09-07 06:13:20 -0700969
970 us->max_xfer_blk = blk;
971}
wdenkaffae2b2002-08-17 09:36:01 +0000972
Simon Glassb9560ad2017-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 Trimarchia0cb3fc2008-12-10 15:52:06 +0100975 int retry, i;
976 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000977 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100978 memset(&srb->cmd[0], 0, 12);
979 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200980 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-04-12 16:34:33 +0530985 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100986 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000987 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200988 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000989
Michael Trimarchia0cb3fc2008-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 Glassb9560ad2017-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;
wdenk80885a92004-02-26 23:46:20 +00001000
Michael Trimarchia0cb3fc2008-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ès99e9ed12010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001005 srb->cmd[4] = 18;
1006 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +02001007 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001008 srb->cmdlen = 12;
1009 ss->transport(srb, ss);
Vivek Gautamceb49722013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001013 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001014 return 0;
1015}
1016
Simon Glassb9560ad2017-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 Denk9c998aa2005-07-21 11:57:57 +02001019 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001020
wdenkaffae2b2002-08-17 09:36:01 +00001021 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001022 memset(&srb->cmd[0], 0, 12);
1023 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001024 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001025 srb->datalen = 0;
1026 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-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ébaudeau3e8581b2012-08-10 18:27:11 +02001030 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001031 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-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 Frysinger5b84dd62012-03-05 13:47:00 +00001042 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001043 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001044
wdenkaffae2b2002-08-17 09:36:01 +00001045 return -1;
1046}
1047
Simon Glassb9560ad2017-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001051 /* XXX retries */
1052 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001053 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001054 memset(&srb->cmd[0], 0, 12);
1055 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001056 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001061 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001062
wdenkaffae2b2002-08-17 09:36:01 +00001063 return -1;
1064}
1065
Simon Glassb9560ad2017-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 memset(&srb->cmd[0], 0, 12);
1070 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001071 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-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 Gautamceb49722013-04-12 16:34:33 +05301079 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001080 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001081}
1082
Simon Glassb9560ad2017-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 Jain127e1082009-11-03 12:22:10 +05301085{
1086 memset(&srb->cmd[0], 0, 12);
1087 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001088 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-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 Gautamceb49722013-04-12 16:34:33 +05301096 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301097 return ss->transport(srb, ss);
1098}
1099
wdenkaffae2b2002-08-17 09:36:01 +00001100
Bartlomiej Siekaddde6b72006-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 Glass4101f682016-02-29 15:25:34 -07001109 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-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 Trimarchia0cb3fc2008-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 Siekaddde6b72006-08-22 10:38:18 +02001120 }
1121}
1122#endif /* CONFIG_USB_BIN_FIXUP */
1123
Simon Glass07b2b782016-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 Glass4101f682016-02-29 15:25:34 -07001128static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001129 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001130#endif
wdenkaffae2b2002-08-17 09:36:01 +00001131{
Gabe Blacke81e79e2012-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 Glass9807c3b2016-02-29 15:25:54 -07001135 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001136 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001137 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001138 struct scsi_cmd *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001139#ifdef CONFIG_BLK
1140 struct blk_desc *block_dev;
1141#endif
wdenkf8d813e2004-03-02 14:05:39 +00001142
1143 if (blkcnt == 0)
1144 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001145 /* Setup device */
Simon Glass07b2b782016-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 Glass9807c3b2016-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 Glass84073b62015-03-25 12:22:13 -06001154 debug("%s: No device\n", __func__);
1155 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001156 }
Simon Glass07b2b782016-02-29 15:25:58 -07001157#endif
Simon Glass9807c3b2016-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 Glass9807c3b2016-02-29 15:25:54 -07001161 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001162 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001163 start = blknr;
1164 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001165
Masahiro Yamadadee37fc2018-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001168
wdenkaffae2b2002-08-17 09:36:01 +00001169 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001170 /* XXX need some comment here */
1171 retry = 2;
1172 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001173 if (blks > ss->max_xfer_blk)
1174 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001175 else
1176 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001177retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001178 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001179 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001180 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001181 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001182 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301183 debug("Read ERROR\n");
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);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001194 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001195
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001196 debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301197 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001198
wdenkaffae2b2002-08-17 09:36:01 +00001199 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001200 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001201 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001202 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001203}
1204
Simon Glass07b2b782016-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 Glass4101f682016-02-29 15:25:34 -07001209static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001210 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001211#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301212{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001213 lbaint_t start, blks;
1214 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301215 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001216 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001217 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001218 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001219 struct scsi_cmd *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001220#ifdef CONFIG_BLK
1221 struct blk_desc *block_dev;
1222#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301223
1224 if (blkcnt == 0)
1225 return 0;
1226
Mahavir Jain127e1082009-11-03 12:22:10 +05301227 /* Setup device */
Simon Glass07b2b782016-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 Glass9807c3b2016-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 Glass84073b62015-03-25 12:22:13 -06001237 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001238 }
Simon Glass07b2b782016-02-29 15:25:58 -07001239#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001240 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301241
1242 usb_disable_asynch(1); /* asynch transfer not allowed */
1243
Simon Glass9807c3b2016-02-29 15:25:54 -07001244 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001245 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301246 start = blknr;
1247 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301248
Masahiro Yamadadee37fc2018-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 Jain127e1082009-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 Meng6158d0b2017-09-07 06:13:20 -07001258 if (blks > ss->max_xfer_blk)
1259 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301260 else
1261 smallblks = (unsigned short) blks;
1262retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001263 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301264 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001265 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301266 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001267 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301268 debug("Write ERROR\n");
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);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001279 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301280
Masahiro Yamadadee37fc2018-08-06 20:47:40 +09001281 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1282 start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301283
1284 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001285 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001286 debug("\n");
Mahavir Jain127e1082009-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 Trimarchia0cb3fc2008-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 Rix8f8bd562009-10-31 12:37:38 -05001295 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001296 int i;
Vivek Gautam605bd752013-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 Rix8f8bd562009-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 Glass1d5827a2015-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 Denk9c998aa2005-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 Gautamceb49722013-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 Rinif5fb78a2015-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 Gautamceb49722013-04-12 16:34:33 +05301326 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001327 switch (ss->protocol) {
1328 case US_PR_CB:
Vivek Gautamceb49722013-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 Gautamceb49722013-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;
wdenk149dded2003-09-10 18:20:28 +00001339 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301340 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-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:
wdenk80885a92004-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 Rix8f8bd562009-10-31 12:37:38 -05001355 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-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 Gautam605bd752013-04-12 16:34:34 +05301358 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001359 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001364 ss->ep_out =
Vivek Gautam605bd752013-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 Gautam605bd752013-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 Gautamceb49722013-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 Rix8f8bd562009-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 Gautamceb49722013-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 */
wdenk149dded2003-09-10 18:20:28 +00001388 /* We only handle certain protocols. Currently, these are
1389 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001390 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001391 */
wdenk80885a92004-02-26 23:46:20 +00001392 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1393 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001404 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001405 }
Bin Meng6158d0b2017-09-07 06:13:20 -07001406
1407 /* Set the maximum transfer size per host controller setting */
Bin Mengea7fad92017-09-07 06:13:21 -07001408 usb_stor_set_max_xfer_blk(dev, ss);
Bin Meng6158d0b2017-09-07 06:13:20 -07001409
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001410 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001411 return 1;
1412}
1413
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001414int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001415 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001416{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001417 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-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 Glassb9560ad2017-06-14 21:28:30 -06001421 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001422
Wolfgang Denk9c998aa2005-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 Gautamceb49722013-04-12 16:34:33 +05301427 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001428
Simon Glass1d5827a2015-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 Glass1d5827a2015-03-25 12:22:12 -06001432 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001433
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001434 perq = usb_stor_buf[0];
1435 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001436
Soeren Moch6a559bb2014-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 Glass1d5827a2015-03-25 12:22:12 -06001442 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001443 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001444 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001445 if ((modi&0x80) == 0x80) {
1446 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001447 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001448 }
Sergey Temerkhanovf6570872015-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 Denk9c998aa2005-07-21 11:57:57 +02001452 dev_desc->vendor[8] = 0;
1453 dev_desc->product[16] = 0;
1454 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001455#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001456 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1457 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001458#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301459 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1460 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-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 Kisky1e5eca72017-04-10 18:23:11 -07001466 if (dev_desc->removable == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001467 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001468 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001469 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001470 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-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 Denk9c998aa2005-07-21 11:57:57 +02001474 cap[0] = 2880;
1475 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001476 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001477 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001480 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1481 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001482
Christian Eggersc9182612008-05-21 22:12:00 +02001483 cap[0] = cpu_to_be32(cap[0]);
1484 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001485#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001486
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001487 capacity = be32_to_cpu(cap[0]) + 1;
1488 blksz = be32_to_cpu(cap[1]);
1489
1490 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1491 dev_desc->lba = capacity;
1492 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001493 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001494 dev_desc->type = perq;
Vivek Gautamceb49722013-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 Glassacf277a2015-03-25 12:22:16 -06001499
1500#ifdef CONFIG_DM_USB
1501
1502static int usb_mass_storage_probe(struct udevice *dev)
1503{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001504 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-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 Glass07b2b782016-02-29 15:25:58 -07001524#ifdef CONFIG_BLK
1525 .platdata_auto_alloc_size = sizeof(struct us_data),
1526#endif
Simon Glassacf277a2015-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 Glassabb59cf2015-07-06 16:47:51 -06001542U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001543#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001544
Simon Glass07b2b782016-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 Glassc0543bf2016-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 Glassacf277a2015-03-25 12:22:16 -06001563#endif