blob: 9cd64744f8ab9c5c4bf07ab08b4d1702e6cf4094 [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 Glass4fd074d2014-10-15 04:38:38 -060039#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060040#include <mapmem.h>
Simon Glasscf92e052015-09-02 17:24:58 -060041#include <memalign.h>
Christian Eggersc9182612008-05-21 22:12:00 +020042#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000043#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060044#include <dm/device-internal.h>
Simon Glass07b2b782016-02-29 15:25:58 -070045#include <dm/lists.h>
wdenkaffae2b2002-08-17 09:36:01 +000046
Grant Likely735dd972007-02-20 09:04:34 +010047#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000048#include <usb.h>
49
wdenk80885a92004-02-26 23:46:20 +000050#undef BBB_COMDAT_TRACE
51#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000052
wdenkaffae2b2002-08-17 09:36:01 +000053#include <scsi.h>
54/* direction table -- this indicates the direction of the data
55 * transfer for each command code -- a 1 indicates input
56 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040057static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000058 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
59 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
62};
63#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
64
Simon Glassb9560ad2017-06-14 21:28:30 -060065static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010066static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000067
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010068static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000069
Simon Glass07b2b782016-02-29 15:25:58 -070070#ifndef CONFIG_BLK
Simon Glass4101f682016-02-29 15:25:34 -070071static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -070072#endif
wdenkaffae2b2002-08-17 09:36:01 +000073
74struct us_data;
Simon Glassb9560ad2017-06-14 21:28:30 -060075typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010076typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000077
78struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010079 struct usb_device *pusb_dev; /* this usb_device */
80
81 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020082# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010083 unsigned char ifnum; /* interface number */
84 unsigned char ep_in; /* in endpoint */
85 unsigned char ep_out; /* out ....... */
86 unsigned char ep_int; /* interrupt . */
87 unsigned char subclass; /* as in overview */
88 unsigned char protocol; /* .............. */
89 unsigned char attention_done; /* force attn on first cmd */
90 unsigned short ip_data; /* interrupt data */
91 int action; /* what to do */
92 int ip_wanted; /* needed */
93 int *irq_handle; /* for USB int requests */
94 unsigned int irqpipe; /* pipe for release_irq */
95 unsigned char irqmaxp; /* max packed for irq Pipe */
96 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Simon Glassb9560ad2017-06-14 21:28:30 -060097 struct scsi_cmd *srb; /* current srb */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010098 trans_reset transport_reset; /* reset routine */
99 trans_cmnd transport; /* transport routine */
Bin Meng6158d0b2017-09-07 06:13:20 -0700100 unsigned short max_xfer_blk; /* maximum transfer blocks */
wdenkaffae2b2002-08-17 09:36:01 +0000101};
102
Simon Glass07b2b782016-02-29 15:25:58 -0700103#ifndef CONFIG_BLK
wdenkaffae2b2002-08-17 09:36:01 +0000104static struct us_data usb_stor[USB_MAX_STOR_DEV];
Simon Glass07b2b782016-02-29 15:25:58 -0700105#endif
wdenkaffae2b2002-08-17 09:36:01 +0000106
wdenk80885a92004-02-26 23:46:20 +0000107#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000108#define USB_STOR_TRANSPORT_FAILED -1
109#define USB_STOR_TRANSPORT_ERROR -2
110
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100111int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
Simon Glass4101f682016-02-29 15:25:34 -0700112 struct blk_desc *dev_desc);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100113int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
114 struct us_data *ss);
Simon Glass07b2b782016-02-29 15:25:58 -0700115#ifdef CONFIG_BLK
116static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
117 lbaint_t blkcnt, void *buffer);
118static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
119 lbaint_t blkcnt, const void *buffer);
120#else
Simon Glass4101f682016-02-29 15:25:34 -0700121static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700122 lbaint_t blkcnt, void *buffer);
Simon Glass4101f682016-02-29 15:25:34 -0700123static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -0700124 lbaint_t blkcnt, const void *buffer);
Simon Glass07b2b782016-02-29 15:25:58 -0700125#endif
wdenkaffae2b2002-08-17 09:36:01 +0000126void uhci_show_temp_int_td(void);
127
Kim Phillips199adb62012-10-29 13:34:32 +0000128static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000129{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200130 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000131}
132
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100133/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200134 * show info on storage devices; 'usb start/init' must be invoked earlier
135 * as we only retrieve structures populated during devices initialization
136 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100137int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200138{
Simon Glass9807c3b2016-02-29 15:25:54 -0700139 int count = 0;
Simon Glass07b2b782016-02-29 15:25:58 -0700140#ifdef CONFIG_BLK
141 struct udevice *dev;
142
143 for (blk_first_device(IF_TYPE_USB, &dev);
144 dev;
145 blk_next_device(&dev)) {
146 struct blk_desc *desc = dev_get_uclass_platdata(dev);
147
148 printf(" Device %d: ", desc->devnum);
149 dev_print(desc);
150 count++;
151 }
152#else
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200153 int i;
154
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100155 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200156 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100157 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200158 dev_print(&usb_dev_desc[i]);
159 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100160 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100161 }
Simon Glass07b2b782016-02-29 15:25:58 -0700162#endif
Simon Glass9807c3b2016-02-29 15:25:54 -0700163 if (!count) {
164 printf("No storage devices, perhaps not 'usb start'ed..?\n");
165 return 1;
166 }
167
Simon Glassb94fc852016-03-16 07:45:44 -0600168 return 0;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200169}
170
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200171static unsigned int usb_get_max_lun(struct us_data *us)
172{
173 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530174 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200175 len = usb_control_msg(us->pusb_dev,
176 usb_rcvctrlpipe(us->pusb_dev, 0),
177 US_BBB_GET_MAX_LUN,
178 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
179 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530180 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200181 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530182 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530183 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200184}
185
Simon Glass9807c3b2016-02-29 15:25:54 -0700186static int usb_stor_probe_device(struct usb_device *udev)
Simon Glass91557572015-03-25 12:22:15 -0600187{
Simon Glass9807c3b2016-02-29 15:25:54 -0700188 int lun, max_lun;
Simon Glass07b2b782016-02-29 15:25:58 -0700189
190#ifdef CONFIG_BLK
191 struct us_data *data;
Simon Glass07b2b782016-02-29 15:25:58 -0700192 int ret;
193#else
Simon Glass9807c3b2016-02-29 15:25:54 -0700194 int start;
195
196 if (udev == NULL)
Simon Glass91557572015-03-25 12:22:15 -0600197 return -ENOENT; /* no more devices available */
Simon Glass07b2b782016-02-29 15:25:58 -0700198#endif
Simon Glass91557572015-03-25 12:22:15 -0600199
Simon Glass07b2b782016-02-29 15:25:58 -0700200 debug("\n\nProbing for storage\n");
201#ifdef CONFIG_BLK
202 /*
203 * We store the us_data in the mass storage device's platdata. It
204 * is shared by all LUNs (block devices) attached to this mass storage
205 * device.
206 */
207 data = dev_get_platdata(udev->dev);
208 if (!usb_storage_probe(udev, 0, data))
209 return 0;
210 max_lun = usb_get_max_lun(data);
211 for (lun = 0; lun <= max_lun; lun++) {
212 struct blk_desc *blkdev;
213 struct udevice *dev;
Simon Glass9107c972016-05-01 11:36:29 -0600214 char str[10];
Simon Glass07b2b782016-02-29 15:25:58 -0700215
Simon Glass9107c972016-05-01 11:36:29 -0600216 snprintf(str, sizeof(str), "lun%d", lun);
217 ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
218 IF_TYPE_USB, usb_max_devs, 512, 0,
219 &dev);
Simon Glass07b2b782016-02-29 15:25:58 -0700220 if (ret) {
221 debug("Cannot bind driver\n");
222 return ret;
223 }
224
225 blkdev = dev_get_uclass_platdata(dev);
226 blkdev->target = 0xff;
227 blkdev->lun = lun;
228
229 ret = usb_stor_get_info(udev, data, blkdev);
230 if (ret == 1)
231 ret = blk_prepare_device(dev);
232 if (!ret) {
233 usb_max_devs++;
234 debug("%s: Found device %p\n", __func__, udev);
235 } else {
236 debug("usb_stor_get_info: Invalid device\n");
237 ret = device_unbind(dev);
238 if (ret)
239 return ret;
240 }
241 }
242#else
Simon Glassc89e79d2016-02-29 15:25:53 -0700243 /* We don't have space to even probe if we hit the maximum */
244 if (usb_max_devs == USB_MAX_STOR_DEV) {
245 printf("max USB Storage Device reached: %d stopping\n",
246 usb_max_devs);
247 return -ENOSPC;
248 }
249
Simon Glass9807c3b2016-02-29 15:25:54 -0700250 if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
251 return 0;
Simon Glass91557572015-03-25 12:22:15 -0600252
Simon Glass9807c3b2016-02-29 15:25:54 -0700253 /*
254 * OK, it's a storage device. Iterate over its LUNs and populate
255 * usb_dev_desc'
256 */
257 start = usb_max_devs;
Simon Glass91557572015-03-25 12:22:15 -0600258
Simon Glass9807c3b2016-02-29 15:25:54 -0700259 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
260 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
261 lun++) {
262 struct blk_desc *blkdev;
Simon Glass91557572015-03-25 12:22:15 -0600263
Simon Glass9807c3b2016-02-29 15:25:54 -0700264 blkdev = &usb_dev_desc[usb_max_devs];
265 memset(blkdev, '\0', sizeof(struct blk_desc));
266 blkdev->if_type = IF_TYPE_USB;
267 blkdev->devnum = usb_max_devs;
268 blkdev->part_type = PART_TYPE_UNKNOWN;
269 blkdev->target = 0xff;
270 blkdev->type = DEV_TYPE_UNKNOWN;
271 blkdev->block_read = usb_stor_read;
272 blkdev->block_write = usb_stor_write;
273 blkdev->lun = lun;
274 blkdev->priv = udev;
275
276 if (usb_stor_get_info(udev, &usb_stor[start],
277 &usb_dev_desc[usb_max_devs]) == 1) {
Simon Glass07b2b782016-02-29 15:25:58 -0700278 debug("partype: %d\n", blkdev->part_type);
279 part_init(blkdev);
280 debug("partype: %d\n", blkdev->part_type);
Simon Glass9807c3b2016-02-29 15:25:54 -0700281 usb_max_devs++;
282 debug("%s: Found device %p\n", __func__, udev);
Simon Glass91557572015-03-25 12:22:15 -0600283 }
284 }
Simon Glass07b2b782016-02-29 15:25:58 -0700285#endif
Simon Glass91557572015-03-25 12:22:15 -0600286
Simon Glass91557572015-03-25 12:22:15 -0600287 return 0;
288}
289
290void usb_stor_reset(void)
291{
292 usb_max_devs = 0;
293}
294
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100295/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200296 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000297 * to the user if mode = 1
298 * returns current device or -1 if no
299 */
300int usb_stor_scan(int mode)
301{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100302 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200303 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100304
Michal Simekb9847002016-12-21 09:35:08 +0100305#ifndef CONFIG_DM_USB
306 unsigned char i;
307
wdenkaffae2b2002-08-17 09:36:01 +0000308 usb_disable_asynch(1); /* asynch transfer not allowed */
309
Simon Glass91557572015-03-25 12:22:15 -0600310 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100311 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600312 struct usb_device *dev;
313
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100314 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530315 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600316 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000317 break;
wdenkaffae2b2002-08-17 09:36:01 +0000318 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200319
wdenkaffae2b2002-08-17 09:36:01 +0000320 usb_disable_asynch(0); /* asynch transfer allowed */
Michal Simekb9847002016-12-21 09:35:08 +0100321#endif
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200322 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100323 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000324 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100325 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000326}
327
328static int usb_stor_irq(struct usb_device *dev)
329{
330 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100331 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000332
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100333 if (us->ip_wanted)
334 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000335 return 0;
336}
337
338
Vivek Gautamceb49722013-04-12 16:34:33 +0530339#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000340
Simon Glassb9560ad2017-06-14 21:28:30 -0600341static void usb_show_srb(struct scsi_cmd *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000342{
343 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100344 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
345 for (i = 0; i < 12; i++)
346 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000347 printf("\n");
348}
349
350static void display_int_status(unsigned long tmp)
351{
352 printf("Status: %s %s %s %s %s %s %s\n",
353 (tmp & USB_ST_ACTIVE) ? "Active" : "",
354 (tmp & USB_ST_STALLED) ? "Stalled" : "",
355 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
356 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
357 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
358 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
359 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
360}
361#endif
362/***********************************************************************
363 * Data transfer routines
364 ***********************************************************************/
365
366static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
367{
368 int max_size;
369 int this_xfer;
370 int result;
371 int partial;
372 int maxtry;
373 int stat;
374
375 /* determine the maximum packet size for these transfers */
376 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
377
378 /* while we have data left to transfer */
379 while (length) {
380
381 /* calculate how long this will be -- maximum or a remainder */
382 this_xfer = length > max_size ? max_size : length;
383 length -= this_xfer;
384
385 /* setup the retry counter */
386 maxtry = 10;
387
388 /* set up the transfer loop */
389 do {
390 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600391 debug("Bulk xfer 0x%lx(%d) try #%d\n",
392 (ulong)map_to_sysmem(buf), this_xfer,
393 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000394 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100395 this_xfer, &partial,
396 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530397 debug("bulk_msg returned %d xferred %d/%d\n",
398 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100399 if (us->pusb_dev->status != 0) {
400 /* if we stall, we need to clear it before
401 * we go on
402 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530403#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000404 display_int_status(us->pusb_dev->status);
405#endif
406 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530407 debug("stalled ->clearing endpoint" \
408 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000409 stat = us->pusb_dev->status;
410 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100411 us->pusb_dev->status = stat;
412 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530413 debug("bulk transferred" \
414 "with error %lX," \
415 " but data ok\n",
416 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000417 return 0;
418 }
419 else
420 return result;
421 }
422 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530423 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000424 return result;
425 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530426 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100427 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530428 debug(" %ld, but data ok\n",
429 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000430 return 0;
431 }
432 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530433 debug(" %ld, data %d\n",
434 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000435 if (!maxtry--)
436 return result;
437 }
438 /* update to show what data was transferred */
439 this_xfer -= partial;
440 buf += partial;
441 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100442 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000443 }
444
445 /* if we get here, we're done and successful */
446 return 0;
447}
448
wdenk149dded2003-09-10 18:20:28 +0000449static int usb_stor_BBB_reset(struct us_data *us)
450{
451 int result;
452 unsigned int pipe;
453
454 /*
455 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
456 *
457 * For Reset Recovery the host shall issue in the following order:
458 * a) a Bulk-Only Mass Storage Reset
459 * b) a Clear Feature HALT to the Bulk-In endpoint
460 * c) a Clear Feature HALT to the Bulk-Out endpoint
461 *
462 * This is done in 3 steps.
463 *
464 * If the reset doesn't succeed, the device should be port reset.
465 *
466 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
467 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530468 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100469 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
470 US_BBB_RESET,
471 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000472 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200473
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100474 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530475 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000476 return -1;
477 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200478
wdenk149dded2003-09-10 18:20:28 +0000479 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000480 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530481 debug("BBB_reset result %d: status %lX reset\n",
482 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000483 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
484 result = usb_clear_halt(us->pusb_dev, pipe);
485 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000486 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530487 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
488 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000489 /* long wait for reset */
490 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
491 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000492 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530493 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
494 result, us->pusb_dev->status);
495 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000496 return 0;
497}
498
wdenkaffae2b2002-08-17 09:36:01 +0000499/* FIXME: this reset function doesn't really reset the port, and it
500 * should. Actually it should probably do what it's doing here, and
501 * reset the port physically
502 */
503static int usb_stor_CB_reset(struct us_data *us)
504{
505 unsigned char cmd[12];
506 int result;
507
Vivek Gautamceb49722013-04-12 16:34:33 +0530508 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100509 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000510 cmd[0] = SCSI_SEND_DIAG;
511 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100512 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
513 US_CBI_ADSC,
514 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
515 0, us->ifnum, cmd, sizeof(cmd),
516 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000517
518 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000519 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530520 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
521 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000522 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
523 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
524
Vivek Gautamceb49722013-04-12 16:34:33 +0530525 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000526 return 0;
527}
528
wdenk149dded2003-09-10 18:20:28 +0000529/*
530 * Set up the command for a BBB device. Note that the actual SCSI
531 * command is copied into cbw.CBWCDB.
532 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600533static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000534{
535 int result;
536 int actlen;
537 int dir_in;
538 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600539 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000540
541 dir_in = US_DIRECTION(srb->cmd[0]);
542
543#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530544 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100545 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
546 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000547 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100548 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000549 printf("cmd[%d] %#x ", result, srb->cmd[result]);
550 printf("\n");
551 }
552#endif
553 /* sanity checks */
554 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530555 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000556 return -1;
557 }
558
559 /* always OUT to the ep */
560 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
561
Puneet Saxenaf5766132012-04-03 14:56:06 +0530562 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
563 cbw->dCBWTag = cpu_to_le32(CBWTag++);
564 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
565 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
566 cbw->bCBWLUN = srb->lun;
567 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000568 /* copy the command data into the CBW command data buffer */
569 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300570
Puneet Saxenaf5766132012-04-03 14:56:06 +0530571 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
572 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100573 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000574 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530575 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000576 return result;
577}
578
wdenkaffae2b2002-08-17 09:36:01 +0000579/* FIXME: we also need a CBI_command which sets up the completion
580 * interrupt, and waits for it
581 */
Simon Glassb9560ad2017-06-14 21:28:30 -0600582static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000583{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200584 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100585 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000586 unsigned int pipe;
587 unsigned long status;
588
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100589 retry = 5;
590 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000591
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100592 if (dir_in)
593 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
594 else
595 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
596
597 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530598 debug("CBI gets a command: Try %d\n", 5 - retry);
599#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000600 usb_show_srb(srb);
601#endif
602 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100603 result = usb_control_msg(us->pusb_dev,
604 usb_sndctrlpipe(us->pusb_dev , 0),
605 US_CBI_ADSC,
606 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000607 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100608 srb->cmd, srb->cmdlen,
609 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530610 debug("CB_transport: control msg returned %d, status %lX\n",
611 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000612 /* check the return code for the command */
613 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100614 if (us->pusb_dev->status & USB_ST_STALLED) {
615 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530616 debug(" stall during command found," \
617 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100618 usb_clear_halt(us->pusb_dev,
619 usb_sndctrlpipe(us->pusb_dev, 0));
620 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000621 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530622 debug(" error during command %02X" \
623 " Stat = %lX\n", srb->cmd[0],
624 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000625 return result;
626 }
627 /* transfer the data payload for this command, if one exists*/
628
Vivek Gautamceb49722013-04-12 16:34:33 +0530629 debug("CB_transport: control msg returned %d," \
630 " direction is %s to go 0x%lx\n", result,
631 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000632 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100633 result = us_one_transfer(us, pipe, (char *)srb->pdata,
634 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530635 debug("CBI attempted to transfer data," \
636 " result is %d status %lX, len %d\n",
637 result, us->pusb_dev->status,
638 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100639 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000640 break;
641 } /* if (srb->datalen) */
642 else
643 break;
644 }
645 /* return result */
646
647 return result;
648}
649
650
Simon Glassb9560ad2017-06-14 21:28:30 -0600651static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000652{
653 int timeout;
654
wdenk80885a92004-02-26 23:46:20 +0000655 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100656 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000657 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
658 timeout = 1000;
659 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300660 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000661 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000662 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000663 }
664 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100665 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000666 us->ip_wanted = 0;
667 return USB_STOR_TRANSPORT_ERROR;
668 }
Vagrant Cascadiana6f70a32016-03-15 12:16:39 -0700669 debug("Got interrupt data 0x%x, transferred %d status 0x%lX\n",
Vivek Gautamceb49722013-04-12 16:34:33 +0530670 us->ip_data, us->pusb_dev->irq_act_len,
671 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000672 /* UFI gives us ASC and ASCQ, like a request sense */
673 if (us->subclass == US_SC_UFI) {
674 if (srb->cmd[0] == SCSI_REQ_SENSE ||
675 srb->cmd[0] == SCSI_INQUIRY)
676 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000677 else if (us->ip_data)
678 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000679 else
wdenk80885a92004-02-26 23:46:20 +0000680 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000681 }
682 /* otherwise, we interpret the data normally */
683 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000684 case 0x0001:
685 return USB_STOR_TRANSPORT_GOOD;
686 case 0x0002:
687 return USB_STOR_TRANSPORT_FAILED;
688 default:
689 return USB_STOR_TRANSPORT_ERROR;
690 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000691 return USB_STOR_TRANSPORT_ERROR;
692}
693
694#define USB_TRANSPORT_UNKNOWN_RETRY 5
695#define USB_TRANSPORT_NOT_READY_RETRY 10
696
wdenk149dded2003-09-10 18:20:28 +0000697/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000698static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000699{
wdenk149dded2003-09-10 18:20:28 +0000700 /* ENDPOINT_HALT = 0, so set value to 0 */
Masahiro Yamada8319aeb2016-09-06 22:17:35 +0900701 return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
702 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
703 endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000704}
705
Simon Glassb9560ad2017-06-14 21:28:30 -0600706static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000707{
708 int result, retry;
709 int dir_in;
710 int actlen, data_actlen;
711 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600712 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000713#ifdef BBB_XPORT_TRACE
714 unsigned char *ptr;
715 int index;
716#endif
717
718 dir_in = US_DIRECTION(srb->cmd[0]);
719
720 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530721 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000722 result = usb_stor_BBB_comdat(srb, us);
723 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530724 debug("failed to send CBW status %ld\n",
725 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000726 usb_stor_BBB_reset(us);
727 return USB_STOR_TRANSPORT_FAILED;
728 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200729 if (!(us->flags & USB_READY))
730 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000731 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
732 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
733 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000734 data_actlen = 0;
735 /* no data, go immediately to the STATUS phase */
736 if (srb->datalen == 0)
737 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530738 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000739 if (dir_in)
740 pipe = pipein;
741 else
742 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300743
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100744 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
745 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000746 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100747 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530748 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000749 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100750 result = usb_stor_BBB_clear_endpt_stall(us,
751 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000752 if (result >= 0)
753 /* continue on to STATUS phase */
754 goto st;
755 }
756 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530757 debug("usb_bulk_msg error status %ld\n",
758 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000759 usb_stor_BBB_reset(us);
760 return USB_STOR_TRANSPORT_FAILED;
761 }
762#ifdef BBB_XPORT_TRACE
763 for (index = 0; index < data_actlen; index++)
764 printf("pdata[%d] %#x ", index, srb->pdata[index]);
765 printf("\n");
766#endif
767 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100768st:
wdenk149dded2003-09-10 18:20:28 +0000769 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100770again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530771 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530772 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200773 &actlen, USB_CNTL_TIMEOUT*5);
774
wdenk149dded2003-09-10 18:20:28 +0000775 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100776 if ((result < 0) && (retry < 1) &&
777 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530778 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000779 /* clear the STALL on the endpoint */
780 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
781 if (result >= 0 && (retry++ < 1))
782 /* do a retry */
783 goto again;
784 }
785 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530786 debug("usb_bulk_msg error status %ld\n",
787 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000788 usb_stor_BBB_reset(us);
789 return USB_STOR_TRANSPORT_FAILED;
790 }
791#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530792 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000793 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
794 printf("ptr[%d] %#x ", index, ptr[index]);
795 printf("\n");
796#endif
797 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530798 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000799 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
800 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530801 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530802 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000803 usb_stor_BBB_reset(us);
804 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530805 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530806 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000807 usb_stor_BBB_reset(us);
808 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530809 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530810 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000811 usb_stor_BBB_reset(us);
812 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530813 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530814 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000815 usb_stor_BBB_reset(us);
816 return USB_STOR_TRANSPORT_FAILED;
817 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530818 debug("transferred %dB instead of %ldB\n",
819 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000820 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530821 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530822 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000823 return USB_STOR_TRANSPORT_FAILED;
824 }
825
826 return result;
827}
828
Simon Glassb9560ad2017-06-14 21:28:30 -0600829static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000830{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100831 int result, status;
Simon Glassb9560ad2017-06-14 21:28:30 -0600832 struct scsi_cmd *psrb;
833 struct scsi_cmd reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100834 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000835
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200836 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100837 status = USB_STOR_TRANSPORT_GOOD;
838 retry = 0;
839 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000840 /* issue the command */
841do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100842 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530843 debug("command / Data returned %d, status %lX\n",
844 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100846 if (us->protocol == US_PR_CBI) {
847 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000848 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100849 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530850 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000851 return status;
852 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
854 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
855 if (!us->ip_data) {
856 /* if the status is good, report it */
857 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530858 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000859 return status;
860 }
861 }
862 }
863 /* do we have to issue an auto request? */
864 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100865 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530866 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000867 us->transport_reset(us);
868 return USB_STOR_TRANSPORT_ERROR;
869 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 if ((us->protocol == US_PR_CBI) &&
871 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
872 (srb->cmd[0] == SCSI_INQUIRY))) {
873 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530874 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000875 return USB_STOR_TRANSPORT_GOOD;
876 }
877 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878 memset(&psrb->cmd[0], 0, 12);
879 psrb->cmd[0] = SCSI_REQ_SENSE;
880 psrb->cmd[1] = srb->lun << 5;
881 psrb->cmd[4] = 18;
882 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200883 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100884 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000885 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100886 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530887 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000888 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100889 if (us->protocol == US_PR_CBI)
890 status = usb_stor_CBI_get_status(psrb, us);
891
892 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530893 debug(" AUTO REQUEST ERROR %ld\n",
894 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000895 return USB_STOR_TRANSPORT_ERROR;
896 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530897 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
898 srb->sense_buf[0], srb->sense_buf[2],
899 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000900 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100901 if ((srb->sense_buf[2] == 0) &&
902 (srb->sense_buf[12] == 0) &&
903 (srb->sense_buf[13] == 0)) {
904 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000905 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906 }
907
wdenkaffae2b2002-08-17 09:36:01 +0000908 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100909 switch (srb->sense_buf[2]) {
910 case 0x01:
911 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000912 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000913 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 case 0x02:
915 /* Not Ready */
916 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
917 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
918 " 0x%02X (NOT READY)\n", srb->cmd[0],
919 srb->sense_buf[0], srb->sense_buf[2],
920 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000921 return USB_STOR_TRANSPORT_FAILED;
922 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000923 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000924 goto do_retry;
925 }
926 break;
927 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100928 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
929 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
930 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
931 srb->sense_buf[2], srb->sense_buf[12],
932 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000933 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100934 } else
wdenk149dded2003-09-10 18:20:28 +0000935 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000936 break;
wdenkaffae2b2002-08-17 09:36:01 +0000937 }
938 return USB_STOR_TRANSPORT_FAILED;
939}
940
Bin Mengea7fad92017-09-07 06:13:21 -0700941static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
942 struct us_data *us)
Bin Meng6158d0b2017-09-07 06:13:20 -0700943{
944 unsigned short blk;
Bin Mengea7fad92017-09-07 06:13:21 -0700945 size_t __maybe_unused size;
946 int __maybe_unused ret;
Bin Meng6158d0b2017-09-07 06:13:20 -0700947
Bin Mengea7fad92017-09-07 06:13:21 -0700948#ifndef CONFIG_DM_USB
Bin Meng6158d0b2017-09-07 06:13:20 -0700949#ifdef CONFIG_USB_EHCI_HCD
950 /*
951 * The U-Boot EHCI driver can handle any transfer length as long as
952 * there is enough free heap space left, but the SCSI READ(10) and
953 * WRITE(10) commands are limited to 65535 blocks.
954 */
955 blk = USHRT_MAX;
956#else
957 blk = 20;
958#endif
Bin Mengea7fad92017-09-07 06:13:21 -0700959#else
960 ret = usb_get_max_xfer_size(udev, (size_t *)&size);
961 if (ret < 0) {
962 /* unimplemented, let's use default 20 */
963 blk = 20;
964 } else {
965 if (size > USHRT_MAX * 512)
Bin Meng72ac8f32017-09-27 21:50:07 -0700966 size = USHRT_MAX * 512;
Bin Mengea7fad92017-09-07 06:13:21 -0700967 blk = size / 512;
968 }
969#endif
Bin Meng6158d0b2017-09-07 06:13:20 -0700970
971 us->max_xfer_blk = blk;
972}
wdenkaffae2b2002-08-17 09:36:01 +0000973
Simon Glassb9560ad2017-06-14 21:28:30 -0600974static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000975{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 int retry, i;
977 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000978 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100979 memset(&srb->cmd[0], 0, 12);
980 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200981 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100982 srb->cmd[4] = 36;
983 srb->datalen = 36;
984 srb->cmdlen = 12;
985 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530986 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000988 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200989 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000990
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100991 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000992 printf("error in inquiry\n");
993 return -1;
994 }
995 return 0;
996}
997
Simon Glassb9560ad2017-06-14 21:28:30 -0600998static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000999{
1000 char *ptr;
wdenk80885a92004-02-26 23:46:20 +00001001
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001002 ptr = (char *)srb->pdata;
1003 memset(&srb->cmd[0], 0, 12);
1004 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001005 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001006 srb->cmd[4] = 18;
1007 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +02001008 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001009 srb->cmdlen = 12;
1010 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +05301011 debug("Request Sense returned %02X %02X %02X\n",
1012 srb->sense_buf[2], srb->sense_buf[12],
1013 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001014 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +00001015 return 0;
1016}
1017
Simon Glassb9560ad2017-06-14 21:28:30 -06001018static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001019{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001020 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +00001021
wdenkaffae2b2002-08-17 09:36:01 +00001022 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001023 memset(&srb->cmd[0], 0, 12);
1024 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001025 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001026 srb->datalen = 0;
1027 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001028 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
1029 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +00001030 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001031 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001032 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -08001033 /*
1034 * Check the Key Code Qualifier, if it matches
1035 * "Not Ready - medium not present"
1036 * (the sense Key equals 0x2 and the ASC is 0x3a)
1037 * return immediately as the medium being absent won't change
1038 * unless there is a user action.
1039 */
1040 if ((srb->sense_buf[2] == 0x02) &&
1041 (srb->sense_buf[12] == 0x3a))
1042 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +00001043 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +00001045
wdenkaffae2b2002-08-17 09:36:01 +00001046 return -1;
1047}
1048
Simon Glassb9560ad2017-06-14 21:28:30 -06001049static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001050{
1051 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001052 /* XXX retries */
1053 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +00001054 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 memset(&srb->cmd[0], 0, 12);
1056 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001057 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001058 srb->datalen = 8;
1059 srb->cmdlen = 12;
1060 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +00001061 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001062 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +00001063
wdenkaffae2b2002-08-17 09:36:01 +00001064 return -1;
1065}
1066
Simon Glassb9560ad2017-06-14 21:28:30 -06001067static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
1068 unsigned long start, unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001069{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001070 memset(&srb->cmd[0], 0, 12);
1071 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001072 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001073 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1074 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1075 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1076 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1077 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1078 srb->cmd[8] = (unsigned char) blocks & 0xff;
1079 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301080 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001081 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001082}
1083
Simon Glassb9560ad2017-06-14 21:28:30 -06001084static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
1085 unsigned long start, unsigned short blocks)
Mahavir Jain127e1082009-11-03 12:22:10 +05301086{
1087 memset(&srb->cmd[0], 0, 12);
1088 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001089 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301090 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1091 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1092 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1093 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1094 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1095 srb->cmd[8] = (unsigned char) blocks & 0xff;
1096 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301097 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301098 return ss->transport(srb, ss);
1099}
1100
wdenkaffae2b2002-08-17 09:36:01 +00001101
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001102#ifdef CONFIG_USB_BIN_FIXUP
1103/*
1104 * Some USB storage devices queried for SCSI identification data respond with
1105 * binary strings, which if output to the console freeze the terminal. The
1106 * workaround is to modify the vendor and product strings read from such
1107 * device with proper values (as reported by 'usb info').
1108 *
1109 * Vendor and product length limits are taken from the definition of
Simon Glass4101f682016-02-29 15:25:34 -07001110 * struct blk_desc in include/part.h.
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001111 */
1112static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1113 unsigned char vendor[],
1114 unsigned char product[]) {
1115 const unsigned char max_vendor_len = 40;
1116 const unsigned char max_product_len = 20;
1117 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001118 strncpy((char *)vendor, "SMSC", max_vendor_len);
1119 strncpy((char *)product, "Flash Media Cntrller",
1120 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001121 }
1122}
1123#endif /* CONFIG_USB_BIN_FIXUP */
1124
Simon Glass07b2b782016-02-29 15:25:58 -07001125#ifdef CONFIG_BLK
1126static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
1127 lbaint_t blkcnt, void *buffer)
1128#else
Simon Glass4101f682016-02-29 15:25:34 -07001129static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001130 lbaint_t blkcnt, void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001131#endif
wdenkaffae2b2002-08-17 09:36:01 +00001132{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001133 lbaint_t start, blks;
1134 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001135 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001136 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001137 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001138 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001139 struct scsi_cmd *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001140#ifdef CONFIG_BLK
1141 struct blk_desc *block_dev;
1142#endif
wdenkf8d813e2004-03-02 14:05:39 +00001143
1144 if (blkcnt == 0)
1145 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001146 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001147#ifdef CONFIG_BLK
1148 block_dev = dev_get_uclass_platdata(dev);
1149 udev = dev_get_parent_priv(dev_get_parent(dev));
1150 debug("\nusb_read: udev %d\n", block_dev->devnum);
1151#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001152 debug("\nusb_read: udev %d\n", block_dev->devnum);
1153 udev = usb_dev_desc[block_dev->devnum].priv;
1154 if (!udev) {
Simon Glass84073b62015-03-25 12:22:13 -06001155 debug("%s: No device\n", __func__);
1156 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001157 }
Simon Glass07b2b782016-02-29 15:25:58 -07001158#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001159 ss = (struct us_data *)udev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001160
1161 usb_disable_asynch(1); /* asynch transfer not allowed */
Simon Glass9807c3b2016-02-29 15:25:54 -07001162 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001163 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001164 start = blknr;
1165 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001166
Simon Glass9807c3b2016-02-29 15:25:54 -07001167 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1168 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001169
wdenkaffae2b2002-08-17 09:36:01 +00001170 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001171 /* XXX need some comment here */
1172 retry = 2;
1173 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001174 if (blks > ss->max_xfer_blk)
1175 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001176 else
1177 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001178retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001179 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001180 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001181 srb->datalen = block_dev->blksz * smallblks;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001182 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001183 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301184 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001185 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001186 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001187 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001188 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001189 break;
1190 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001191 start += smallblks;
1192 blks -= smallblks;
1193 buf_addr += srb->datalen;
1194 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001195 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001196
Vivek Gautamceb49722013-04-12 16:34:33 +05301197 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001198 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301199 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001200
wdenkaffae2b2002-08-17 09:36:01 +00001201 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001202 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001203 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001204 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001205}
1206
Simon Glass07b2b782016-02-29 15:25:58 -07001207#ifdef CONFIG_BLK
1208static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
1209 lbaint_t blkcnt, const void *buffer)
1210#else
Simon Glass4101f682016-02-29 15:25:34 -07001211static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
Stephen Warren7c4213f2015-12-07 11:38:48 -07001212 lbaint_t blkcnt, const void *buffer)
Simon Glass07b2b782016-02-29 15:25:58 -07001213#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301214{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001215 lbaint_t start, blks;
1216 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301217 unsigned short smallblks;
Simon Glass9807c3b2016-02-29 15:25:54 -07001218 struct usb_device *udev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001219 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001220 int retry;
Simon Glassb9560ad2017-06-14 21:28:30 -06001221 struct scsi_cmd *srb = &usb_ccb;
Simon Glass07b2b782016-02-29 15:25:58 -07001222#ifdef CONFIG_BLK
1223 struct blk_desc *block_dev;
1224#endif
Mahavir Jain127e1082009-11-03 12:22:10 +05301225
1226 if (blkcnt == 0)
1227 return 0;
1228
Mahavir Jain127e1082009-11-03 12:22:10 +05301229 /* Setup device */
Simon Glass07b2b782016-02-29 15:25:58 -07001230#ifdef CONFIG_BLK
1231 block_dev = dev_get_uclass_platdata(dev);
1232 udev = dev_get_parent_priv(dev_get_parent(dev));
1233 debug("\nusb_read: udev %d\n", block_dev->devnum);
1234#else
Simon Glass9807c3b2016-02-29 15:25:54 -07001235 debug("\nusb_read: udev %d\n", block_dev->devnum);
1236 udev = usb_dev_desc[block_dev->devnum].priv;
1237 if (!udev) {
1238 debug("%s: No device\n", __func__);
Simon Glass84073b62015-03-25 12:22:13 -06001239 return 0;
Simon Glass9807c3b2016-02-29 15:25:54 -07001240 }
Simon Glass07b2b782016-02-29 15:25:58 -07001241#endif
Simon Glass9807c3b2016-02-29 15:25:54 -07001242 ss = (struct us_data *)udev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301243
1244 usb_disable_asynch(1); /* asynch transfer not allowed */
1245
Simon Glass9807c3b2016-02-29 15:25:54 -07001246 srb->lun = block_dev->lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001247 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301248 start = blknr;
1249 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301250
Simon Glass9807c3b2016-02-29 15:25:54 -07001251 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
1252 PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301253
1254 do {
1255 /* If write fails retry for max retry count else
1256 * return with number of blocks written successfully.
1257 */
1258 retry = 2;
1259 srb->pdata = (unsigned char *)buf_addr;
Bin Meng6158d0b2017-09-07 06:13:20 -07001260 if (blks > ss->max_xfer_blk)
1261 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301262 else
1263 smallblks = (unsigned short) blks;
1264retry_it:
Bin Meng6158d0b2017-09-07 06:13:20 -07001265 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301266 usb_show_progress();
Simon Glass9807c3b2016-02-29 15:25:54 -07001267 srb->datalen = block_dev->blksz * smallblks;
Mahavir Jain127e1082009-11-03 12:22:10 +05301268 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001269 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301270 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001271 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301272 if (retry--)
1273 goto retry_it;
1274 blkcnt -= blks;
1275 break;
1276 }
1277 start += smallblks;
1278 blks -= smallblks;
1279 buf_addr += srb->datalen;
1280 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001281 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301282
Simon Glass4fd074d2014-10-15 04:38:38 -06001283 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1284 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301285
1286 usb_disable_asynch(0); /* asynch transfer allowed */
Bin Meng6158d0b2017-09-07 06:13:20 -07001287 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001288 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301289 return blkcnt;
1290
1291}
wdenkaffae2b2002-08-17 09:36:01 +00001292
1293/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001294int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1295 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001296{
Tom Rix8f8bd562009-10-31 12:37:38 -05001297 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001298 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301299 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001300 unsigned int flags = 0;
1301
wdenkaffae2b2002-08-17 09:36:01 +00001302 /* let's examine the device now */
1303 iface = &dev->config.if_desc[ifnum];
1304
wdenkaffae2b2002-08-17 09:36:01 +00001305 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001306 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1307 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1308 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001309 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001310 /* if it's not a mass storage, we go no further */
1311 return 0;
1312 }
1313
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001314 memset(ss, 0, sizeof(struct us_data));
1315
wdenkaffae2b2002-08-17 09:36:01 +00001316 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301317 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001318
1319 /* Initialize the us_data structure with some useful info */
1320 ss->flags = flags;
1321 ss->ifnum = ifnum;
1322 ss->pusb_dev = dev;
1323 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001324 ss->subclass = iface->desc.bInterfaceSubClass;
1325 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001326
1327 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301328 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001329 switch (ss->protocol) {
1330 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301331 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001332 ss->transport = usb_stor_CB_transport;
1333 ss->transport_reset = usb_stor_CB_reset;
1334 break;
1335
1336 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301337 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001338 ss->transport = usb_stor_CB_transport;
1339 ss->transport_reset = usb_stor_CB_reset;
1340 break;
wdenk149dded2003-09-10 18:20:28 +00001341 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301342 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001343 ss->transport = usb_stor_BBB_transport;
1344 ss->transport_reset = usb_stor_BBB_reset;
1345 break;
wdenkaffae2b2002-08-17 09:36:01 +00001346 default:
wdenk80885a92004-02-26 23:46:20 +00001347 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001348 return 0;
1349 break;
1350 }
1351
1352 /*
1353 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1354 * An optional interrupt is OK (necessary for CBI protocol).
1355 * We will ignore any others.
1356 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001357 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301358 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001359 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301360 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001361 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301362 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1363 ss->ep_in = ep_desc->bEndpointAddress &
1364 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001365 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001366 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301367 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001368 USB_ENDPOINT_NUMBER_MASK;
1369 }
1370
1371 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301372 if ((ep_desc->bmAttributes &
1373 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1374 ss->ep_int = ep_desc->bEndpointAddress &
1375 USB_ENDPOINT_NUMBER_MASK;
1376 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001377 }
1378 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301379 debug("Endpoints In %d Out %d Int %d\n",
1380 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001381
1382 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001383 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001384 !ss->ep_in || !ss->ep_out ||
1385 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301386 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001387 return 0;
1388 }
1389 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001390 /* We only handle certain protocols. Currently, these are
1391 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001392 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001393 */
wdenk80885a92004-02-26 23:46:20 +00001394 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1395 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001396 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001397 return 0;
1398 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001399 if (ss->ep_int) {
1400 /* we had found an interrupt endpoint, prepare irq pipe
1401 * set up the IRQ pipe and handler
1402 */
wdenkaffae2b2002-08-17 09:36:01 +00001403 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1404 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1405 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001406 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001407 }
Bin Meng6158d0b2017-09-07 06:13:20 -07001408
1409 /* Set the maximum transfer size per host controller setting */
Bin Mengea7fad92017-09-07 06:13:21 -07001410 usb_stor_set_max_xfer_blk(dev, ss);
Bin Meng6158d0b2017-09-07 06:13:20 -07001411
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001412 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001413 return 1;
1414}
1415
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001416int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
Simon Glass4101f682016-02-29 15:25:34 -07001417 struct blk_desc *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001418{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001419 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001420 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1421 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1422 u32 capacity, blksz;
Simon Glassb9560ad2017-06-14 21:28:30 -06001423 struct scsi_cmd *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001424
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001425 pccb->pdata = usb_stor_buf;
1426
1427 dev_desc->target = dev->devnum;
1428 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301429 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001430
Simon Glass1d5827a2015-03-25 12:22:12 -06001431 if (usb_inquiry(pccb, ss)) {
1432 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001433 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001434 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001435
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001436 perq = usb_stor_buf[0];
1437 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001438
Soeren Moch6a559bb2014-11-08 07:02:14 +01001439 /*
1440 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1441 * they would not respond to test_unit_ready .
1442 */
1443 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001444 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001445 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001446 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001447 if ((modi&0x80) == 0x80) {
1448 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001449 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001450 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001451 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1452 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1453 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001454 dev_desc->vendor[8] = 0;
1455 dev_desc->product[16] = 0;
1456 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001457#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001458 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1459 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001460#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301461 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1462 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001463 if (usb_test_unit_ready(pccb, ss)) {
1464 printf("Device NOT ready\n"
1465 " Request Sense returned %02X %02X %02X\n",
1466 pccb->sense_buf[2], pccb->sense_buf[12],
1467 pccb->sense_buf[13]);
Troy Kisky1e5eca72017-04-10 18:23:11 -07001468 if (dev_desc->removable == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001469 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001470 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001471 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001472 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001473 memset(pccb->pdata, 0, 8);
1474 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001475 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001476 cap[0] = 2880;
1477 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001478 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001479 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001480 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001481#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001482 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1483 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001484
Christian Eggersc9182612008-05-21 22:12:00 +02001485 cap[0] = cpu_to_be32(cap[0]);
1486 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001487#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001488
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001489 capacity = be32_to_cpu(cap[0]) + 1;
1490 blksz = be32_to_cpu(cap[1]);
1491
1492 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1493 dev_desc->lba = capacity;
1494 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001495 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001496 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301497 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001498
wdenkaffae2b2002-08-17 09:36:01 +00001499 return 1;
1500}
Simon Glassacf277a2015-03-25 12:22:16 -06001501
1502#ifdef CONFIG_DM_USB
1503
1504static int usb_mass_storage_probe(struct udevice *dev)
1505{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001506 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001507 int ret;
1508
1509 usb_disable_asynch(1); /* asynch transfer not allowed */
1510 ret = usb_stor_probe_device(udev);
1511 usb_disable_asynch(0); /* asynch transfer allowed */
1512
1513 return ret;
1514}
1515
1516static const struct udevice_id usb_mass_storage_ids[] = {
1517 { .compatible = "usb-mass-storage" },
1518 { }
1519};
1520
1521U_BOOT_DRIVER(usb_mass_storage) = {
1522 .name = "usb_mass_storage",
1523 .id = UCLASS_MASS_STORAGE,
1524 .of_match = usb_mass_storage_ids,
1525 .probe = usb_mass_storage_probe,
Simon Glass07b2b782016-02-29 15:25:58 -07001526#ifdef CONFIG_BLK
1527 .platdata_auto_alloc_size = sizeof(struct us_data),
1528#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001529};
1530
1531UCLASS_DRIVER(usb_mass_storage) = {
1532 .id = UCLASS_MASS_STORAGE,
1533 .name = "usb_mass_storage",
1534};
1535
1536static const struct usb_device_id mass_storage_id_table[] = {
1537 {
1538 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1539 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1540 },
1541 { } /* Terminating entry */
1542};
1543
Simon Glassabb59cf2015-07-06 16:47:51 -06001544U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glass07b2b782016-02-29 15:25:58 -07001545#endif
Simon Glassacf277a2015-03-25 12:22:16 -06001546
Simon Glass07b2b782016-02-29 15:25:58 -07001547#ifdef CONFIG_BLK
1548static const struct blk_ops usb_storage_ops = {
1549 .read = usb_stor_read,
1550 .write = usb_stor_write,
1551};
1552
1553U_BOOT_DRIVER(usb_storage_blk) = {
1554 .name = "usb_storage_blk",
1555 .id = UCLASS_BLK,
1556 .ops = &usb_storage_ops,
1557};
Simon Glassc0543bf2016-05-01 11:36:06 -06001558#else
1559U_BOOT_LEGACY_BLK(usb) = {
1560 .if_typename = "usb",
1561 .if_type = IF_TYPE_USB,
1562 .max_devs = USB_MAX_STOR_DEV,
1563 .desc = usb_dev_desc,
1564};
Simon Glassacf277a2015-03-25 12:22:16 -06001565#endif