blob: ee4468ef88b0b70c440dfb496b509234fb681a90 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-08-04 01:14:12 +02002 * Most of this source has been derived from the Linux USB
3 * project:
4 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
5 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
6 * (c) 1999 Michael Gee (michael@linuxspecific.com)
7 * (c) 2000 Yggdrasil Computing, Inc.
8 *
9 *
10 * Adapted for U-Boot:
11 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
wdenkaffae2b2002-08-17 09:36:01 +000012 *
wdenk149dded2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000015 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000017 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000018 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020019 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +000020 */
21
22/* Note:
23 * Currently only the CBI transport protocoll has been implemented, and it
24 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
25 * transport protocoll may work as well.
26 */
wdenk149dded2003-09-10 18:20:28 +000027/*
28 * New Note:
29 * Support for USB Mass Storage Devices (BBB) has been added. It has
30 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000031 */
wdenkaffae2b2002-08-17 09:36:01 +000032
33
wdenkaffae2b2002-08-17 09:36:01 +000034#include <common.h>
35#include <command.h>
Simon Glass91557572015-03-25 12:22:15 -060036#include <errno.h>
Simon Glass4fd074d2014-10-15 04:38:38 -060037#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060038#include <mapmem.h>
Christian Eggersc9182612008-05-21 22:12:00 +020039#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000040#include <asm/processor.h>
41
Grant Likely735dd972007-02-20 09:04:34 +010042#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000043#include <usb.h>
44
wdenk80885a92004-02-26 23:46:20 +000045#undef BBB_COMDAT_TRACE
46#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000047
wdenkaffae2b2002-08-17 09:36:01 +000048#include <scsi.h>
49/* direction table -- this indicates the direction of the data
50 * transfer for each command code -- a 1 indicates input
51 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040052static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000053 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
54 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
57};
58#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
59
Puneet Saxenaf5766132012-04-03 14:56:06 +053060static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010061static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000062
wdenkaffae2b2002-08-17 09:36:01 +000063#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010064static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000065
66static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
67
68struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010069typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
70typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000071
72struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010073 struct usb_device *pusb_dev; /* this usb_device */
74
75 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020076# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010077 unsigned char ifnum; /* interface number */
78 unsigned char ep_in; /* in endpoint */
79 unsigned char ep_out; /* out ....... */
80 unsigned char ep_int; /* interrupt . */
81 unsigned char subclass; /* as in overview */
82 unsigned char protocol; /* .............. */
83 unsigned char attention_done; /* force attn on first cmd */
84 unsigned short ip_data; /* interrupt data */
85 int action; /* what to do */
86 int ip_wanted; /* needed */
87 int *irq_handle; /* for USB int requests */
88 unsigned int irqpipe; /* pipe for release_irq */
89 unsigned char irqmaxp; /* max packed for irq Pipe */
90 unsigned char irqinterval; /* Intervall for IRQ Pipe */
91 ccb *srb; /* current srb */
92 trans_reset transport_reset; /* reset routine */
93 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000094};
95
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +020096#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +000097/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +020098 * The U-Boot EHCI driver can handle any transfer length as long as there is
99 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
100 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000101 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200102#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200103#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200104#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200105#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000106
wdenkaffae2b2002-08-17 09:36:01 +0000107static struct us_data usb_stor[USB_MAX_STOR_DEV];
108
109
wdenk80885a92004-02-26 23:46:20 +0000110#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000111#define USB_STOR_TRANSPORT_FAILED -1
112#define USB_STOR_TRANSPORT_ERROR -2
113
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100114int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
115 block_dev_desc_t *dev_desc);
116int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
117 struct us_data *ss);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200118unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000119 lbaint_t blkcnt, void *buffer);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200120unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000121 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000122struct usb_device * usb_get_dev_index(int index);
123void uhci_show_temp_int_td(void);
124
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000125#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000126block_dev_desc_t *usb_stor_get_dev(int index)
127{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200128 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000129}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000130#endif
wdenkaffae2b2002-08-17 09:36:01 +0000131
Kim Phillips199adb62012-10-29 13:34:32 +0000132static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000133{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200134 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000135}
136
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100137/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200138 * show info on storage devices; 'usb start/init' must be invoked earlier
139 * as we only retrieve structures populated during devices initialization
140 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100141int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200142{
143 int i;
144
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100145 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200146 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100147 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200148 dev_print(&usb_dev_desc[i]);
149 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100150 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100151 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700152
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100153 printf("No storage devices, perhaps not 'usb start'ed..?\n");
154 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200155}
156
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200157static unsigned int usb_get_max_lun(struct us_data *us)
158{
159 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530160 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200161 len = usb_control_msg(us->pusb_dev,
162 usb_rcvctrlpipe(us->pusb_dev, 0),
163 US_BBB_GET_MAX_LUN,
164 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
165 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530166 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200167 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530168 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530169 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200170}
171
Simon Glass91557572015-03-25 12:22:15 -0600172static int usb_stor_probe_device(struct usb_device *dev)
173{
174 if (dev == NULL)
175 return -ENOENT; /* no more devices available */
176
177 debug("\n\nProbing for storage\n");
178 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
179 /* OK, it's a storage device. Iterate over its LUNs
180 * and populate `usb_dev_desc'.
181 */
182 int lun, max_lun, start = usb_max_devs;
183
184 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
185 for (lun = 0;
186 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
187 lun++) {
188 struct block_dev_desc *blkdev;
189
190 blkdev = &usb_dev_desc[usb_max_devs];
191 memset(blkdev, '\0', sizeof(block_dev_desc_t));
192 blkdev->if_type = IF_TYPE_USB;
193 blkdev->dev = usb_max_devs;
194 blkdev->part_type = PART_TYPE_UNKNOWN;
195 blkdev->target = 0xff;
196 blkdev->type = DEV_TYPE_UNKNOWN;
197 blkdev->block_read = usb_stor_read;
198 blkdev->block_write = usb_stor_write;
199 blkdev->lun = lun;
200 blkdev->priv = dev;
201
202 if (usb_stor_get_info(dev, &usb_stor[start],
203 &usb_dev_desc[usb_max_devs]) ==
204 1) {
205 usb_max_devs++;
206 debug("%s: Found device %p\n", __func__, dev);
207 }
208 }
209 }
210
211 /* if storage device */
212 if (usb_max_devs == USB_MAX_STOR_DEV) {
213 printf("max USB Storage Device reached: %d stopping\n",
214 usb_max_devs);
215 return -ENOSPC;
216 }
217
218 return 0;
219}
220
221void usb_stor_reset(void)
222{
223 usb_max_devs = 0;
224}
225
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100226/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200227 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000228 * to the user if mode = 1
229 * returns current device or -1 if no
230 */
231int usb_stor_scan(int mode)
232{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600233 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000234
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100235 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200236 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100237
wdenkaffae2b2002-08-17 09:36:01 +0000238 usb_disable_asynch(1); /* asynch transfer not allowed */
239
Simon Glass91557572015-03-25 12:22:15 -0600240 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100241 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600242 struct usb_device *dev;
243
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530245 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600246 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000247 break;
wdenkaffae2b2002-08-17 09:36:01 +0000248 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200249
wdenkaffae2b2002-08-17 09:36:01 +0000250 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200251 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100252 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000253 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100254 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000255}
256
257static int usb_stor_irq(struct usb_device *dev)
258{
259 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100260 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000261
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100262 if (us->ip_wanted)
263 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000264 return 0;
265}
266
267
Vivek Gautamceb49722013-04-12 16:34:33 +0530268#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000269
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100270static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000271{
272 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100273 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
274 for (i = 0; i < 12; i++)
275 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000276 printf("\n");
277}
278
279static void display_int_status(unsigned long tmp)
280{
281 printf("Status: %s %s %s %s %s %s %s\n",
282 (tmp & USB_ST_ACTIVE) ? "Active" : "",
283 (tmp & USB_ST_STALLED) ? "Stalled" : "",
284 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
285 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
286 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
287 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
288 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
289}
290#endif
291/***********************************************************************
292 * Data transfer routines
293 ***********************************************************************/
294
295static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
296{
297 int max_size;
298 int this_xfer;
299 int result;
300 int partial;
301 int maxtry;
302 int stat;
303
304 /* determine the maximum packet size for these transfers */
305 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
306
307 /* while we have data left to transfer */
308 while (length) {
309
310 /* calculate how long this will be -- maximum or a remainder */
311 this_xfer = length > max_size ? max_size : length;
312 length -= this_xfer;
313
314 /* setup the retry counter */
315 maxtry = 10;
316
317 /* set up the transfer loop */
318 do {
319 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600320 debug("Bulk xfer 0x%lx(%d) try #%d\n",
321 (ulong)map_to_sysmem(buf), this_xfer,
322 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000323 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100324 this_xfer, &partial,
325 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530326 debug("bulk_msg returned %d xferred %d/%d\n",
327 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100328 if (us->pusb_dev->status != 0) {
329 /* if we stall, we need to clear it before
330 * we go on
331 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530332#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000333 display_int_status(us->pusb_dev->status);
334#endif
335 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530336 debug("stalled ->clearing endpoint" \
337 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000338 stat = us->pusb_dev->status;
339 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100340 us->pusb_dev->status = stat;
341 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530342 debug("bulk transferred" \
343 "with error %lX," \
344 " but data ok\n",
345 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000346 return 0;
347 }
348 else
349 return result;
350 }
351 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530352 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000353 return result;
354 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530355 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100356 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530357 debug(" %ld, but data ok\n",
358 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000359 return 0;
360 }
361 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530362 debug(" %ld, data %d\n",
363 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000364 if (!maxtry--)
365 return result;
366 }
367 /* update to show what data was transferred */
368 this_xfer -= partial;
369 buf += partial;
370 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100371 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000372 }
373
374 /* if we get here, we're done and successful */
375 return 0;
376}
377
wdenk149dded2003-09-10 18:20:28 +0000378static int usb_stor_BBB_reset(struct us_data *us)
379{
380 int result;
381 unsigned int pipe;
382
383 /*
384 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
385 *
386 * For Reset Recovery the host shall issue in the following order:
387 * a) a Bulk-Only Mass Storage Reset
388 * b) a Clear Feature HALT to the Bulk-In endpoint
389 * c) a Clear Feature HALT to the Bulk-Out endpoint
390 *
391 * This is done in 3 steps.
392 *
393 * If the reset doesn't succeed, the device should be port reset.
394 *
395 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
396 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530397 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100398 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
399 US_BBB_RESET,
400 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000401 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200402
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100403 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530404 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000405 return -1;
406 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200407
wdenk149dded2003-09-10 18:20:28 +0000408 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000409 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530410 debug("BBB_reset result %d: status %lX reset\n",
411 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000412 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
413 result = usb_clear_halt(us->pusb_dev, pipe);
414 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000415 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530416 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
417 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000418 /* long wait for reset */
419 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
420 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000421 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530422 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
423 result, us->pusb_dev->status);
424 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000425 return 0;
426}
427
wdenkaffae2b2002-08-17 09:36:01 +0000428/* FIXME: this reset function doesn't really reset the port, and it
429 * should. Actually it should probably do what it's doing here, and
430 * reset the port physically
431 */
432static int usb_stor_CB_reset(struct us_data *us)
433{
434 unsigned char cmd[12];
435 int result;
436
Vivek Gautamceb49722013-04-12 16:34:33 +0530437 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100438 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000439 cmd[0] = SCSI_SEND_DIAG;
440 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100441 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
442 US_CBI_ADSC,
443 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
444 0, us->ifnum, cmd, sizeof(cmd),
445 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000446
447 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000448 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530449 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
450 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000451 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
452 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
453
Vivek Gautamceb49722013-04-12 16:34:33 +0530454 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000455 return 0;
456}
457
wdenk149dded2003-09-10 18:20:28 +0000458/*
459 * Set up the command for a BBB device. Note that the actual SCSI
460 * command is copied into cbw.CBWCDB.
461 */
Kim Phillips199adb62012-10-29 13:34:32 +0000462static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000463{
464 int result;
465 int actlen;
466 int dir_in;
467 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600468 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000469
470 dir_in = US_DIRECTION(srb->cmd[0]);
471
472#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530473 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100474 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
475 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000476 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100477 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000478 printf("cmd[%d] %#x ", result, srb->cmd[result]);
479 printf("\n");
480 }
481#endif
482 /* sanity checks */
483 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530484 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000485 return -1;
486 }
487
488 /* always OUT to the ep */
489 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
490
Puneet Saxenaf5766132012-04-03 14:56:06 +0530491 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
492 cbw->dCBWTag = cpu_to_le32(CBWTag++);
493 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
494 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
495 cbw->bCBWLUN = srb->lun;
496 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000497 /* copy the command data into the CBW command data buffer */
498 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300499
Puneet Saxenaf5766132012-04-03 14:56:06 +0530500 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
501 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100502 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000503 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530504 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000505 return result;
506}
507
wdenkaffae2b2002-08-17 09:36:01 +0000508/* FIXME: we also need a CBI_command which sets up the completion
509 * interrupt, and waits for it
510 */
Kim Phillips199adb62012-10-29 13:34:32 +0000511static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000512{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200513 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100514 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000515 unsigned int pipe;
516 unsigned long status;
517
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100518 retry = 5;
519 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000520
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100521 if (dir_in)
522 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
523 else
524 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
525
526 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530527 debug("CBI gets a command: Try %d\n", 5 - retry);
528#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000529 usb_show_srb(srb);
530#endif
531 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100532 result = usb_control_msg(us->pusb_dev,
533 usb_sndctrlpipe(us->pusb_dev , 0),
534 US_CBI_ADSC,
535 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000536 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100537 srb->cmd, srb->cmdlen,
538 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530539 debug("CB_transport: control msg returned %d, status %lX\n",
540 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000541 /* check the return code for the command */
542 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100543 if (us->pusb_dev->status & USB_ST_STALLED) {
544 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530545 debug(" stall during command found," \
546 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 usb_clear_halt(us->pusb_dev,
548 usb_sndctrlpipe(us->pusb_dev, 0));
549 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000550 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530551 debug(" error during command %02X" \
552 " Stat = %lX\n", srb->cmd[0],
553 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000554 return result;
555 }
556 /* transfer the data payload for this command, if one exists*/
557
Vivek Gautamceb49722013-04-12 16:34:33 +0530558 debug("CB_transport: control msg returned %d," \
559 " direction is %s to go 0x%lx\n", result,
560 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000561 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100562 result = us_one_transfer(us, pipe, (char *)srb->pdata,
563 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530564 debug("CBI attempted to transfer data," \
565 " result is %d status %lX, len %d\n",
566 result, us->pusb_dev->status,
567 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100568 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000569 break;
570 } /* if (srb->datalen) */
571 else
572 break;
573 }
574 /* return result */
575
576 return result;
577}
578
579
Kim Phillips199adb62012-10-29 13:34:32 +0000580static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000581{
582 int timeout;
583
wdenk80885a92004-02-26 23:46:20 +0000584 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100585 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000586 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
587 timeout = 1000;
588 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300589 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000590 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000591 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000592 }
593 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100594 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000595 us->ip_wanted = 0;
596 return USB_STOR_TRANSPORT_ERROR;
597 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530598 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
599 us->ip_data, us->pusb_dev->irq_act_len,
600 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000601 /* UFI gives us ASC and ASCQ, like a request sense */
602 if (us->subclass == US_SC_UFI) {
603 if (srb->cmd[0] == SCSI_REQ_SENSE ||
604 srb->cmd[0] == SCSI_INQUIRY)
605 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000606 else if (us->ip_data)
607 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000608 else
wdenk80885a92004-02-26 23:46:20 +0000609 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000610 }
611 /* otherwise, we interpret the data normally */
612 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000613 case 0x0001:
614 return USB_STOR_TRANSPORT_GOOD;
615 case 0x0002:
616 return USB_STOR_TRANSPORT_FAILED;
617 default:
618 return USB_STOR_TRANSPORT_ERROR;
619 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000620 return USB_STOR_TRANSPORT_ERROR;
621}
622
623#define USB_TRANSPORT_UNKNOWN_RETRY 5
624#define USB_TRANSPORT_NOT_READY_RETRY 10
625
wdenk149dded2003-09-10 18:20:28 +0000626/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000627static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000628{
629 int result;
630
631 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100632 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000633 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000634 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000635 return result;
636}
637
Kim Phillips199adb62012-10-29 13:34:32 +0000638static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000639{
640 int result, retry;
641 int dir_in;
642 int actlen, data_actlen;
643 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600644 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000645#ifdef BBB_XPORT_TRACE
646 unsigned char *ptr;
647 int index;
648#endif
649
650 dir_in = US_DIRECTION(srb->cmd[0]);
651
652 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530653 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000654 result = usb_stor_BBB_comdat(srb, us);
655 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530656 debug("failed to send CBW status %ld\n",
657 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000658 usb_stor_BBB_reset(us);
659 return USB_STOR_TRANSPORT_FAILED;
660 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200661 if (!(us->flags & USB_READY))
662 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000663 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
664 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
665 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000666 data_actlen = 0;
667 /* no data, go immediately to the STATUS phase */
668 if (srb->datalen == 0)
669 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530670 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000671 if (dir_in)
672 pipe = pipein;
673 else
674 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300675
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100676 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
677 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000678 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100679 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530680 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000681 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100682 result = usb_stor_BBB_clear_endpt_stall(us,
683 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000684 if (result >= 0)
685 /* continue on to STATUS phase */
686 goto st;
687 }
688 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530689 debug("usb_bulk_msg error status %ld\n",
690 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000691 usb_stor_BBB_reset(us);
692 return USB_STOR_TRANSPORT_FAILED;
693 }
694#ifdef BBB_XPORT_TRACE
695 for (index = 0; index < data_actlen; index++)
696 printf("pdata[%d] %#x ", index, srb->pdata[index]);
697 printf("\n");
698#endif
699 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100700st:
wdenk149dded2003-09-10 18:20:28 +0000701 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100702again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530703 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530704 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200705 &actlen, USB_CNTL_TIMEOUT*5);
706
wdenk149dded2003-09-10 18:20:28 +0000707 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100708 if ((result < 0) && (retry < 1) &&
709 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530710 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000711 /* clear the STALL on the endpoint */
712 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
713 if (result >= 0 && (retry++ < 1))
714 /* do a retry */
715 goto again;
716 }
717 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530718 debug("usb_bulk_msg error status %ld\n",
719 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000720 usb_stor_BBB_reset(us);
721 return USB_STOR_TRANSPORT_FAILED;
722 }
723#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530724 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000725 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
726 printf("ptr[%d] %#x ", index, ptr[index]);
727 printf("\n");
728#endif
729 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530730 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000731 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
732 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530733 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530734 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000735 usb_stor_BBB_reset(us);
736 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530737 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530738 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000739 usb_stor_BBB_reset(us);
740 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530741 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530742 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000743 usb_stor_BBB_reset(us);
744 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530745 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530746 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000747 usb_stor_BBB_reset(us);
748 return USB_STOR_TRANSPORT_FAILED;
749 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530750 debug("transferred %dB instead of %ldB\n",
751 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000752 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530753 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530754 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000755 return USB_STOR_TRANSPORT_FAILED;
756 }
757
758 return result;
759}
760
Kim Phillips199adb62012-10-29 13:34:32 +0000761static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000762{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100763 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000764 ccb *psrb;
765 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100766 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000767
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200768 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100769 status = USB_STOR_TRANSPORT_GOOD;
770 retry = 0;
771 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000772 /* issue the command */
773do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100774 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530775 debug("command / Data returned %d, status %lX\n",
776 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000777 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100778 if (us->protocol == US_PR_CBI) {
779 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000780 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100781 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530782 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000783 return status;
784 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100785 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
786 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
787 if (!us->ip_data) {
788 /* if the status is good, report it */
789 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530790 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000791 return status;
792 }
793 }
794 }
795 /* do we have to issue an auto request? */
796 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100797 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530798 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000799 us->transport_reset(us);
800 return USB_STOR_TRANSPORT_ERROR;
801 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100802 if ((us->protocol == US_PR_CBI) &&
803 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
804 (srb->cmd[0] == SCSI_INQUIRY))) {
805 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530806 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000807 return USB_STOR_TRANSPORT_GOOD;
808 }
809 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100810 memset(&psrb->cmd[0], 0, 12);
811 psrb->cmd[0] = SCSI_REQ_SENSE;
812 psrb->cmd[1] = srb->lun << 5;
813 psrb->cmd[4] = 18;
814 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200815 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100816 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000817 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100818 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530819 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000820 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100821 if (us->protocol == US_PR_CBI)
822 status = usb_stor_CBI_get_status(psrb, us);
823
824 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530825 debug(" AUTO REQUEST ERROR %ld\n",
826 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000827 return USB_STOR_TRANSPORT_ERROR;
828 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530829 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
830 srb->sense_buf[0], srb->sense_buf[2],
831 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000832 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100833 if ((srb->sense_buf[2] == 0) &&
834 (srb->sense_buf[12] == 0) &&
835 (srb->sense_buf[13] == 0)) {
836 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000837 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100838 }
839
wdenkaffae2b2002-08-17 09:36:01 +0000840 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100841 switch (srb->sense_buf[2]) {
842 case 0x01:
843 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000844 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000845 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100846 case 0x02:
847 /* Not Ready */
848 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
849 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
850 " 0x%02X (NOT READY)\n", srb->cmd[0],
851 srb->sense_buf[0], srb->sense_buf[2],
852 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000853 return USB_STOR_TRANSPORT_FAILED;
854 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000855 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000856 goto do_retry;
857 }
858 break;
859 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100860 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
861 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
862 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
863 srb->sense_buf[2], srb->sense_buf[12],
864 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000865 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 } else
wdenk149dded2003-09-10 18:20:28 +0000867 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000868 break;
wdenkaffae2b2002-08-17 09:36:01 +0000869 }
870 return USB_STOR_TRANSPORT_FAILED;
871}
872
873
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100874static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000875{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100876 int retry, i;
877 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000878 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100879 memset(&srb->cmd[0], 0, 12);
880 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200881 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100882 srb->cmd[4] = 36;
883 srb->datalen = 36;
884 srb->cmdlen = 12;
885 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530886 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100887 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000888 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200889 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000890
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100891 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000892 printf("error in inquiry\n");
893 return -1;
894 }
895 return 0;
896}
897
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100898static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000899{
900 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000901
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100902 ptr = (char *)srb->pdata;
903 memset(&srb->cmd[0], 0, 12);
904 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200905 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906 srb->cmd[4] = 18;
907 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200908 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100909 srb->cmdlen = 12;
910 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530911 debug("Request Sense returned %02X %02X %02X\n",
912 srb->sense_buf[2], srb->sense_buf[12],
913 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000915 return 0;
916}
917
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100918static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000919{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200920 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000921
wdenkaffae2b2002-08-17 09:36:01 +0000922 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923 memset(&srb->cmd[0], 0, 12);
924 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200925 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100926 srb->datalen = 0;
927 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200928 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
929 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000930 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200931 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100932 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800933 /*
934 * Check the Key Code Qualifier, if it matches
935 * "Not Ready - medium not present"
936 * (the sense Key equals 0x2 and the ASC is 0x3a)
937 * return immediately as the medium being absent won't change
938 * unless there is a user action.
939 */
940 if ((srb->sense_buf[2] == 0x02) &&
941 (srb->sense_buf[12] == 0x3a))
942 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000943 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100944 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000945
wdenkaffae2b2002-08-17 09:36:01 +0000946 return -1;
947}
948
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100949static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000950{
951 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100952 /* XXX retries */
953 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000954 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955 memset(&srb->cmd[0], 0, 12);
956 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200957 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 srb->datalen = 8;
959 srb->cmdlen = 12;
960 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000961 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100962 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000963
wdenkaffae2b2002-08-17 09:36:01 +0000964 return -1;
965}
966
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
968 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000969{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100970 memset(&srb->cmd[0], 0, 12);
971 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200972 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100973 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
974 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
975 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
976 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
977 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
978 srb->cmd[8] = (unsigned char) blocks & 0xff;
979 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530980 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100981 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000982}
983
Mahavir Jain127e1082009-11-03 12:22:10 +0530984static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
985 unsigned short blocks)
986{
987 memset(&srb->cmd[0], 0, 12);
988 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200989 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +0530990 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
991 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
992 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
993 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
994 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
995 srb->cmd[8] = (unsigned char) blocks & 0xff;
996 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530997 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +0530998 return ss->transport(srb, ss);
999}
1000
wdenkaffae2b2002-08-17 09:36:01 +00001001
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001002#ifdef CONFIG_USB_BIN_FIXUP
1003/*
1004 * Some USB storage devices queried for SCSI identification data respond with
1005 * binary strings, which if output to the console freeze the terminal. The
1006 * workaround is to modify the vendor and product strings read from such
1007 * device with proper values (as reported by 'usb info').
1008 *
1009 * Vendor and product length limits are taken from the definition of
1010 * block_dev_desc_t in include/part.h.
1011 */
1012static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1013 unsigned char vendor[],
1014 unsigned char product[]) {
1015 const unsigned char max_vendor_len = 40;
1016 const unsigned char max_product_len = 20;
1017 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001018 strncpy((char *)vendor, "SMSC", max_vendor_len);
1019 strncpy((char *)product, "Flash Media Cntrller",
1020 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001021 }
1022}
1023#endif /* CONFIG_USB_BIN_FIXUP */
1024
Sascha Silbeff8fef52013-06-14 13:07:25 +02001025unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001026 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001027{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001028 lbaint_t start, blks;
1029 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001030 unsigned short smallblks;
1031 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001032 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001033 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001034 ccb *srb = &usb_ccb;
1035
1036 if (blkcnt == 0)
1037 return 0;
1038
1039 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001040 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001041 debug("\nusb_read: dev %d\n", device);
1042 dev = usb_dev_desc[device].priv;
1043 if (!dev) {
1044 debug("%s: No device\n", __func__);
1045 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001046 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001047 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001048
1049 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001051 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001052 start = blknr;
1053 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001054
Vivek Gautamceb49722013-04-12 16:34:33 +05301055 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001056 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057
wdenkaffae2b2002-08-17 09:36:01 +00001058 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001059 /* XXX need some comment here */
1060 retry = 2;
1061 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001062 if (blks > USB_MAX_XFER_BLK)
1063 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 else
1065 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001066retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001067 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001068 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1070 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001071 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301072 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001073 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001074 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001075 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001076 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001077 break;
1078 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079 start += smallblks;
1080 blks -= smallblks;
1081 buf_addr += srb->datalen;
1082 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001083 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001084
Vivek Gautamceb49722013-04-12 16:34:33 +05301085 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001086 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301087 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001088
wdenkaffae2b2002-08-17 09:36:01 +00001089 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001090 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001091 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001093}
1094
Sascha Silbeff8fef52013-06-14 13:07:25 +02001095unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001096 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301097{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001098 lbaint_t start, blks;
1099 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301100 unsigned short smallblks;
1101 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001102 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001103 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301104 ccb *srb = &usb_ccb;
1105
1106 if (blkcnt == 0)
1107 return 0;
1108
1109 device &= 0xff;
1110 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001111 debug("\nusb_write: dev %d\n", device);
1112 dev = usb_dev_desc[device].priv;
1113 if (!dev)
1114 return 0;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001115 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301116
1117 usb_disable_asynch(1); /* asynch transfer not allowed */
1118
1119 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001120 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301121 start = blknr;
1122 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301123
Vivek Gautamceb49722013-04-12 16:34:33 +05301124 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001125 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301126
1127 do {
1128 /* If write fails retry for max retry count else
1129 * return with number of blocks written successfully.
1130 */
1131 retry = 2;
1132 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001133 if (blks > USB_MAX_XFER_BLK)
1134 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301135 else
1136 smallblks = (unsigned short) blks;
1137retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001138 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301139 usb_show_progress();
1140 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1141 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001142 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301143 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001144 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301145 if (retry--)
1146 goto retry_it;
1147 blkcnt -= blks;
1148 break;
1149 }
1150 start += smallblks;
1151 blks -= smallblks;
1152 buf_addr += srb->datalen;
1153 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001154 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301155
Simon Glass4fd074d2014-10-15 04:38:38 -06001156 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1157 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301158
1159 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001160 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001161 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301162 return blkcnt;
1163
1164}
wdenkaffae2b2002-08-17 09:36:01 +00001165
1166/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001167int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1168 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001169{
Tom Rix8f8bd562009-10-31 12:37:38 -05001170 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001171 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301172 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001173 unsigned int flags = 0;
1174
1175 int protocol = 0;
1176 int subclass = 0;
1177
wdenkaffae2b2002-08-17 09:36:01 +00001178 /* let's examine the device now */
1179 iface = &dev->config.if_desc[ifnum];
1180
1181#if 0
1182 /* this is the place to patch some storage devices */
Vivek Gautamceb49722013-04-12 16:34:33 +05301183 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001184 dev->descriptor.idProduct);
1185
1186 if ((dev->descriptor.idVendor) == 0x066b &&
1187 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301188 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001189 protocol = US_PR_CB;
1190 subclass = US_SC_UFI; /* an assumption */
1191 }
1192#endif
1193
1194 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001195 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1196 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1197 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001198 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001199 /* if it's not a mass storage, we go no further */
1200 return 0;
1201 }
1202
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001203 memset(ss, 0, sizeof(struct us_data));
1204
wdenkaffae2b2002-08-17 09:36:01 +00001205 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301206 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001207
1208 /* Initialize the us_data structure with some useful info */
1209 ss->flags = flags;
1210 ss->ifnum = ifnum;
1211 ss->pusb_dev = dev;
1212 ss->attention_done = 0;
1213
1214 /* If the device has subclass and protocol, then use that. Otherwise,
1215 * take data from the specific interface.
1216 */
1217 if (subclass) {
1218 ss->subclass = subclass;
1219 ss->protocol = protocol;
1220 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001221 ss->subclass = iface->desc.bInterfaceSubClass;
1222 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001223 }
1224
1225 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301226 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001227 switch (ss->protocol) {
1228 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301229 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001230 ss->transport = usb_stor_CB_transport;
1231 ss->transport_reset = usb_stor_CB_reset;
1232 break;
1233
1234 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301235 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001236 ss->transport = usb_stor_CB_transport;
1237 ss->transport_reset = usb_stor_CB_reset;
1238 break;
wdenk149dded2003-09-10 18:20:28 +00001239 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301240 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001241 ss->transport = usb_stor_BBB_transport;
1242 ss->transport_reset = usb_stor_BBB_reset;
1243 break;
wdenkaffae2b2002-08-17 09:36:01 +00001244 default:
wdenk80885a92004-02-26 23:46:20 +00001245 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001246 return 0;
1247 break;
1248 }
1249
1250 /*
1251 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1252 * An optional interrupt is OK (necessary for CBI protocol).
1253 * We will ignore any others.
1254 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001255 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301256 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001257 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301258 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001259 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301260 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1261 ss->ep_in = ep_desc->bEndpointAddress &
1262 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001263 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001264 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301265 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001266 USB_ENDPOINT_NUMBER_MASK;
1267 }
1268
1269 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301270 if ((ep_desc->bmAttributes &
1271 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1272 ss->ep_int = ep_desc->bEndpointAddress &
1273 USB_ENDPOINT_NUMBER_MASK;
1274 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001275 }
1276 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301277 debug("Endpoints In %d Out %d Int %d\n",
1278 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001279
1280 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001281 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001282 !ss->ep_in || !ss->ep_out ||
1283 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301284 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001285 return 0;
1286 }
1287 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001288 /* We only handle certain protocols. Currently, these are
1289 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001290 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001291 */
wdenk80885a92004-02-26 23:46:20 +00001292 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1293 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001294 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001295 return 0;
1296 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001297 if (ss->ep_int) {
1298 /* we had found an interrupt endpoint, prepare irq pipe
1299 * set up the IRQ pipe and handler
1300 */
wdenkaffae2b2002-08-17 09:36:01 +00001301 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1302 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1303 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001304 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001305 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001306 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001307 return 1;
1308}
1309
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001310int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1311 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001312{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001313 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001314 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1315 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1316 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001317 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001318
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001319 pccb->pdata = usb_stor_buf;
1320
1321 dev_desc->target = dev->devnum;
1322 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301323 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001324
Simon Glass1d5827a2015-03-25 12:22:12 -06001325 if (usb_inquiry(pccb, ss)) {
1326 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001327 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001328 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001329
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001330 perq = usb_stor_buf[0];
1331 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001332
Soeren Moch6a559bb2014-11-08 07:02:14 +01001333 /*
1334 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1335 * they would not respond to test_unit_ready .
1336 */
1337 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001338 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001339 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001340 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001341 if ((modi&0x80) == 0x80) {
1342 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001343 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001344 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001345 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1346 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1347 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001348 dev_desc->vendor[8] = 0;
1349 dev_desc->product[16] = 0;
1350 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001351#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001352 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1353 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001354#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301355 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1356 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001357 if (usb_test_unit_ready(pccb, ss)) {
1358 printf("Device NOT ready\n"
1359 " Request Sense returned %02X %02X %02X\n",
1360 pccb->sense_buf[2], pccb->sense_buf[12],
1361 pccb->sense_buf[13]);
1362 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001363 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001364 return 1;
1365 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001366 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001367 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001368 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001369 memset(pccb->pdata, 0, 8);
1370 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001371 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001372 cap[0] = 2880;
1373 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001374 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001375 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001376 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001377#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001378 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1379 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001380
Christian Eggersc9182612008-05-21 22:12:00 +02001381 cap[0] = cpu_to_be32(cap[0]);
1382 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001383#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001384
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001385 capacity = be32_to_cpu(cap[0]) + 1;
1386 blksz = be32_to_cpu(cap[1]);
1387
1388 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1389 dev_desc->lba = capacity;
1390 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001391 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001392 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301393 debug(" address %d\n", dev_desc->target);
1394 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001395
1396 init_part(dev_desc);
1397
Vivek Gautamceb49722013-04-12 16:34:33 +05301398 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001399 return 1;
1400}