blob: eb7706c100c402a696a4ae57a2dae9bf3b2d2119 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk6a3d6b02005-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 *
wdenkde887eb2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000015 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000017 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000018 *
Wolfgang Denkd79de1d2013-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 */
wdenkde887eb2003-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.
wdenkde887eb2003-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 Glassb43f7682014-10-15 04:38:38 -060036#include <inttypes.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020037#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000038#include <asm/processor.h>
39
Grant Likelyffc2dd72007-02-20 09:04:34 +010040#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000041#include <usb.h>
42
wdenk5f495752004-02-26 23:46:20 +000043#undef BBB_COMDAT_TRACE
44#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000045
wdenkaffae2b2002-08-17 09:36:01 +000046#include <scsi.h>
47/* direction table -- this indicates the direction of the data
48 * transfer for each command code -- a 1 indicates input
49 */
Mike Frysinger165522b2010-10-20 07:16:04 -040050static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000051 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
52 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
55};
56#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
57
Puneet Saxena6c9bb602012-04-03 14:56:06 +053058static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
wdenkaffae2b2002-08-17 09:36:01 +000059
60/*
61 * CBI style
62 */
63
64#define US_CBI_ADSC 0
65
wdenkde887eb2003-09-10 18:20:28 +000066/*
67 * BULK only
68 */
69#define US_BBB_RESET 0xff
70#define US_BBB_GET_MAX_LUN 0xfe
71
72/* Command Block Wrapper */
73typedef struct {
74 __u32 dCBWSignature;
75# define CBWSIGNATURE 0x43425355
76 __u32 dCBWTag;
77 __u32 dCBWDataTransferLength;
78 __u8 bCBWFlags;
79# define CBWFLAGS_OUT 0x00
80# define CBWFLAGS_IN 0x80
81 __u8 bCBWLUN;
82 __u8 bCDBLength;
83# define CBWCDBLENGTH 16
84 __u8 CBWCDB[CBWCDBLENGTH];
85} umass_bbb_cbw_t;
wdenk5f495752004-02-26 23:46:20 +000086#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchi956a4352008-12-10 15:52:06 +010087static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000088
89/* Command Status Wrapper */
90typedef struct {
91 __u32 dCSWSignature;
92# define CSWSIGNATURE 0x53425355
93 __u32 dCSWTag;
94 __u32 dCSWDataResidue;
95 __u8 bCSWStatus;
96# define CSWSTATUS_GOOD 0x0
wdenk5f495752004-02-26 23:46:20 +000097# define CSWSTATUS_FAILED 0x1
wdenkde887eb2003-09-10 18:20:28 +000098# define CSWSTATUS_PHASE 0x2
99} umass_bbb_csw_t;
wdenk5f495752004-02-26 23:46:20 +0000100#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000101
102#define USB_MAX_STOR_DEV 5
Michael Trimarchi956a4352008-12-10 15:52:06 +0100103static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000104
105static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
106
107struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100108typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
109typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000110
111struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100112 struct usb_device *pusb_dev; /* this usb_device */
113
114 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200115# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +0100116 unsigned char ifnum; /* interface number */
117 unsigned char ep_in; /* in endpoint */
118 unsigned char ep_out; /* out ....... */
119 unsigned char ep_int; /* interrupt . */
120 unsigned char subclass; /* as in overview */
121 unsigned char protocol; /* .............. */
122 unsigned char attention_done; /* force attn on first cmd */
123 unsigned short ip_data; /* interrupt data */
124 int action; /* what to do */
125 int ip_wanted; /* needed */
126 int *irq_handle; /* for USB int requests */
127 unsigned int irqpipe; /* pipe for release_irq */
128 unsigned char irqmaxp; /* max packed for irq Pipe */
129 unsigned char irqinterval; /* Intervall for IRQ Pipe */
130 ccb *srb; /* current srb */
131 trans_reset transport_reset; /* reset routine */
132 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000133};
134
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200135#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000136/*
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200137 * The U-Boot EHCI driver can handle any transfer length as long as there is
138 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
139 * limited to 65535 blocks.
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000140 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200141#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200142#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200143#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200144#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000145
wdenkaffae2b2002-08-17 09:36:01 +0000146static struct us_data usb_stor[USB_MAX_STOR_DEV];
147
148
wdenk5f495752004-02-26 23:46:20 +0000149#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000150#define USB_STOR_TRANSPORT_FAILED -1
151#define USB_STOR_TRANSPORT_ERROR -2
152
Michael Trimarchi956a4352008-12-10 15:52:06 +0100153int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
154 block_dev_desc_t *dev_desc);
155int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
156 struct us_data *ss);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200157unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000158 lbaint_t blkcnt, void *buffer);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200159unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000160 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000161struct usb_device * usb_get_dev_index(int index);
162void uhci_show_temp_int_td(void);
163
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000164#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000165block_dev_desc_t *usb_stor_get_dev(int index)
166{
Kim B. Heino300ea512010-03-12 15:46:56 +0200167 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000168}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000169#endif
wdenkaffae2b2002-08-17 09:36:01 +0000170
Kim Phillipsb052b602012-10-29 13:34:32 +0000171static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000172{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200173 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000174}
175
Michael Trimarchi956a4352008-12-10 15:52:06 +0100176/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200177 * show info on storage devices; 'usb start/init' must be invoked earlier
178 * as we only retrieve structures populated during devices initialization
179 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100180int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200181{
182 int i;
183
Aras Vaichas7ede1862008-03-25 12:09:07 +1100184 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200185 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100186 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200187 dev_print(&usb_dev_desc[i]);
188 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100189 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100190 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700191
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100192 printf("No storage devices, perhaps not 'usb start'ed..?\n");
193 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200194}
195
Ludovic Courtès134396c2010-10-05 22:04:26 +0200196static unsigned int usb_get_max_lun(struct us_data *us)
197{
198 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530199 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200200 len = usb_control_msg(us->pusb_dev,
201 usb_rcvctrlpipe(us->pusb_dev, 0),
202 US_BBB_GET_MAX_LUN,
203 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
204 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530205 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200206 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530207 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530208 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200209}
210
Michael Trimarchi956a4352008-12-10 15:52:06 +0100211/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200212 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000213 * to the user if mode = 1
214 * returns current device or -1 if no
215 */
216int usb_stor_scan(int mode)
217{
218 unsigned char i;
219 struct usb_device *dev;
220
Michael Trimarchi956a4352008-12-10 15:52:06 +0100221 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200222 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100223
wdenkaffae2b2002-08-17 09:36:01 +0000224 usb_disable_asynch(1); /* asynch transfer not allowed */
225
Michael Trimarchi956a4352008-12-10 15:52:06 +0100226 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
227 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100228 usb_dev_desc[i].if_type = IF_TYPE_USB;
229 usb_dev_desc[i].dev = i;
230 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200231 usb_dev_desc[i].target = 0xff;
232 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100233 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530234 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000235 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200236
Michael Trimarchi956a4352008-12-10 15:52:06 +0100237 usb_max_devs = 0;
238 for (i = 0; i < USB_MAX_DEVICE; i++) {
239 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530240 debug("i=%d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100241 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100242 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100243
244 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès134396c2010-10-05 22:04:26 +0200245 /* OK, it's a storage device. Iterate over its LUNs
246 * and populate `usb_dev_desc'.
Michael Trimarchi956a4352008-12-10 15:52:06 +0100247 */
Ludovic Courtès134396c2010-10-05 22:04:26 +0200248 int lun, max_lun, start = usb_max_devs;
249
250 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
251 for (lun = 0;
252 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
253 lun++) {
254 usb_dev_desc[usb_max_devs].lun = lun;
255 if (usb_stor_get_info(dev, &usb_stor[start],
Vivek Gautam23cbd292013-04-12 16:34:34 +0530256 &usb_dev_desc[usb_max_devs]) == 1) {
257 usb_max_devs++;
258 }
Ludovic Courtès134396c2010-10-05 22:04:26 +0200259 }
260 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100261 /* if storage device */
262 if (usb_max_devs == USB_MAX_STOR_DEV) {
263 printf("max USB Storage Device reached: %d stopping\n",
264 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000265 break;
266 }
267 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200268
wdenkaffae2b2002-08-17 09:36:01 +0000269 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200270 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100271 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000272 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100273 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000274}
275
276static int usb_stor_irq(struct usb_device *dev)
277{
278 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100279 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000280
Michael Trimarchi956a4352008-12-10 15:52:06 +0100281 if (us->ip_wanted)
282 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000283 return 0;
284}
285
286
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530287#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000288
Michael Trimarchi956a4352008-12-10 15:52:06 +0100289static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000290{
291 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100292 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
293 for (i = 0; i < 12; i++)
294 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000295 printf("\n");
296}
297
298static void display_int_status(unsigned long tmp)
299{
300 printf("Status: %s %s %s %s %s %s %s\n",
301 (tmp & USB_ST_ACTIVE) ? "Active" : "",
302 (tmp & USB_ST_STALLED) ? "Stalled" : "",
303 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
304 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
305 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
306 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
307 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
308}
309#endif
310/***********************************************************************
311 * Data transfer routines
312 ***********************************************************************/
313
314static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
315{
316 int max_size;
317 int this_xfer;
318 int result;
319 int partial;
320 int maxtry;
321 int stat;
322
323 /* determine the maximum packet size for these transfers */
324 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
325
326 /* while we have data left to transfer */
327 while (length) {
328
329 /* calculate how long this will be -- maximum or a remainder */
330 this_xfer = length > max_size ? max_size : length;
331 length -= this_xfer;
332
333 /* setup the retry counter */
334 maxtry = 10;
335
336 /* set up the transfer loop */
337 do {
338 /* transfer the data */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530339 debug("Bulk xfer 0x%x(%d) try #%d\n",
340 (unsigned int)buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000341 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100342 this_xfer, &partial,
343 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530344 debug("bulk_msg returned %d xferred %d/%d\n",
345 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100346 if (us->pusb_dev->status != 0) {
347 /* if we stall, we need to clear it before
348 * we go on
349 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530350#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000351 display_int_status(us->pusb_dev->status);
352#endif
353 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530354 debug("stalled ->clearing endpoint" \
355 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000356 stat = us->pusb_dev->status;
357 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100358 us->pusb_dev->status = stat;
359 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530360 debug("bulk transferred" \
361 "with error %lX," \
362 " but data ok\n",
363 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000364 return 0;
365 }
366 else
367 return result;
368 }
369 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530370 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000371 return result;
372 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530373 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100374 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530375 debug(" %ld, but data ok\n",
376 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000377 return 0;
378 }
379 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530380 debug(" %ld, data %d\n",
381 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000382 if (!maxtry--)
383 return result;
384 }
385 /* update to show what data was transferred */
386 this_xfer -= partial;
387 buf += partial;
388 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100389 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000390 }
391
392 /* if we get here, we're done and successful */
393 return 0;
394}
395
wdenkde887eb2003-09-10 18:20:28 +0000396static int usb_stor_BBB_reset(struct us_data *us)
397{
398 int result;
399 unsigned int pipe;
400
401 /*
402 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
403 *
404 * For Reset Recovery the host shall issue in the following order:
405 * a) a Bulk-Only Mass Storage Reset
406 * b) a Clear Feature HALT to the Bulk-In endpoint
407 * c) a Clear Feature HALT to the Bulk-Out endpoint
408 *
409 * This is done in 3 steps.
410 *
411 * If the reset doesn't succeed, the device should be port reset.
412 *
413 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
414 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530415 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100416 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
417 US_BBB_RESET,
418 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000419 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200420
Michael Trimarchi956a4352008-12-10 15:52:06 +0100421 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530422 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000423 return -1;
424 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200425
wdenkde887eb2003-09-10 18:20:28 +0000426 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000427 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530428 debug("BBB_reset result %d: status %lX reset\n",
429 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000430 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
431 result = usb_clear_halt(us->pusb_dev, pipe);
432 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000433 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530434 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
435 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000436 /* long wait for reset */
437 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
438 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000439 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530440 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
441 result, us->pusb_dev->status);
442 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000443 return 0;
444}
445
wdenkaffae2b2002-08-17 09:36:01 +0000446/* FIXME: this reset function doesn't really reset the port, and it
447 * should. Actually it should probably do what it's doing here, and
448 * reset the port physically
449 */
450static int usb_stor_CB_reset(struct us_data *us)
451{
452 unsigned char cmd[12];
453 int result;
454
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530455 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100456 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000457 cmd[0] = SCSI_SEND_DIAG;
458 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100459 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
460 US_CBI_ADSC,
461 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
462 0, us->ifnum, cmd, sizeof(cmd),
463 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000464
465 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000466 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530467 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
468 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000469 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
470 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
471
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530472 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000473 return 0;
474}
475
wdenkde887eb2003-09-10 18:20:28 +0000476/*
477 * Set up the command for a BBB device. Note that the actual SCSI
478 * command is copied into cbw.CBWCDB.
479 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000480static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000481{
482 int result;
483 int actlen;
484 int dir_in;
485 unsigned int pipe;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530486 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000487
488 dir_in = US_DIRECTION(srb->cmd[0]);
489
490#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530491 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100492 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
493 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000494 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100495 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000496 printf("cmd[%d] %#x ", result, srb->cmd[result]);
497 printf("\n");
498 }
499#endif
500 /* sanity checks */
501 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530502 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000503 return -1;
504 }
505
506 /* always OUT to the ep */
507 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
508
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530509 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
510 cbw->dCBWTag = cpu_to_le32(CBWTag++);
511 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
512 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
513 cbw->bCBWLUN = srb->lun;
514 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000515 /* copy the command data into the CBW command data buffer */
516 /* DST SRC LEN!!! */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530517 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
518 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100519 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000520 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530521 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000522 return result;
523}
524
wdenkaffae2b2002-08-17 09:36:01 +0000525/* FIXME: we also need a CBI_command which sets up the completion
526 * interrupt, and waits for it
527 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000528static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000529{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200530 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100531 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000532 unsigned int pipe;
533 unsigned long status;
534
Michael Trimarchi956a4352008-12-10 15:52:06 +0100535 retry = 5;
536 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000537
Michael Trimarchi956a4352008-12-10 15:52:06 +0100538 if (dir_in)
539 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
540 else
541 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
542
543 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530544 debug("CBI gets a command: Try %d\n", 5 - retry);
545#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000546 usb_show_srb(srb);
547#endif
548 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100549 result = usb_control_msg(us->pusb_dev,
550 usb_sndctrlpipe(us->pusb_dev , 0),
551 US_CBI_ADSC,
552 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000553 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100554 srb->cmd, srb->cmdlen,
555 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530556 debug("CB_transport: control msg returned %d, status %lX\n",
557 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000558 /* check the return code for the command */
559 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100560 if (us->pusb_dev->status & USB_ST_STALLED) {
561 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530562 debug(" stall during command found," \
563 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100564 usb_clear_halt(us->pusb_dev,
565 usb_sndctrlpipe(us->pusb_dev, 0));
566 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000567 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530568 debug(" error during command %02X" \
569 " Stat = %lX\n", srb->cmd[0],
570 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000571 return result;
572 }
573 /* transfer the data payload for this command, if one exists*/
574
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530575 debug("CB_transport: control msg returned %d," \
576 " direction is %s to go 0x%lx\n", result,
577 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000578 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100579 result = us_one_transfer(us, pipe, (char *)srb->pdata,
580 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530581 debug("CBI attempted to transfer data," \
582 " result is %d status %lX, len %d\n",
583 result, us->pusb_dev->status,
584 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100585 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000586 break;
587 } /* if (srb->datalen) */
588 else
589 break;
590 }
591 /* return result */
592
593 return result;
594}
595
596
Kim Phillipsb052b602012-10-29 13:34:32 +0000597static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000598{
599 int timeout;
600
wdenk5f495752004-02-26 23:46:20 +0000601 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100602 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000603 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
604 timeout = 1000;
605 while (timeout--) {
Kim Phillipsb052b602012-10-29 13:34:32 +0000606 if ((volatile int *) us->ip_wanted == NULL)
wdenkaffae2b2002-08-17 09:36:01 +0000607 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000608 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000609 }
610 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100611 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000612 us->ip_wanted = 0;
613 return USB_STOR_TRANSPORT_ERROR;
614 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530615 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
616 us->ip_data, us->pusb_dev->irq_act_len,
617 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000618 /* UFI gives us ASC and ASCQ, like a request sense */
619 if (us->subclass == US_SC_UFI) {
620 if (srb->cmd[0] == SCSI_REQ_SENSE ||
621 srb->cmd[0] == SCSI_INQUIRY)
622 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000623 else if (us->ip_data)
624 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000625 else
wdenk5f495752004-02-26 23:46:20 +0000626 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000627 }
628 /* otherwise, we interpret the data normally */
629 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000630 case 0x0001:
631 return USB_STOR_TRANSPORT_GOOD;
632 case 0x0002:
633 return USB_STOR_TRANSPORT_FAILED;
634 default:
635 return USB_STOR_TRANSPORT_ERROR;
636 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000637 return USB_STOR_TRANSPORT_ERROR;
638}
639
640#define USB_TRANSPORT_UNKNOWN_RETRY 5
641#define USB_TRANSPORT_NOT_READY_RETRY 10
642
wdenkde887eb2003-09-10 18:20:28 +0000643/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000644static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000645{
646 int result;
647
648 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100649 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000650 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000651 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000652 return result;
653}
654
Kim Phillipsb052b602012-10-29 13:34:32 +0000655static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000656{
657 int result, retry;
658 int dir_in;
659 int actlen, data_actlen;
660 unsigned int pipe, pipein, pipeout;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530661 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000662#ifdef BBB_XPORT_TRACE
663 unsigned char *ptr;
664 int index;
665#endif
666
667 dir_in = US_DIRECTION(srb->cmd[0]);
668
669 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530670 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000671 result = usb_stor_BBB_comdat(srb, us);
672 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530673 debug("failed to send CBW status %ld\n",
674 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000675 usb_stor_BBB_reset(us);
676 return USB_STOR_TRANSPORT_FAILED;
677 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200678 if (!(us->flags & USB_READY))
679 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000680 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
681 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
682 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000683 data_actlen = 0;
684 /* no data, go immediately to the STATUS phase */
685 if (srb->datalen == 0)
686 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530687 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000688 if (dir_in)
689 pipe = pipein;
690 else
691 pipe = pipeout;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100692 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
693 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000694 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100695 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530696 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000697 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100698 result = usb_stor_BBB_clear_endpt_stall(us,
699 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000700 if (result >= 0)
701 /* continue on to STATUS phase */
702 goto st;
703 }
704 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530705 debug("usb_bulk_msg error status %ld\n",
706 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000707 usb_stor_BBB_reset(us);
708 return USB_STOR_TRANSPORT_FAILED;
709 }
710#ifdef BBB_XPORT_TRACE
711 for (index = 0; index < data_actlen; index++)
712 printf("pdata[%d] %#x ", index, srb->pdata[index]);
713 printf("\n");
714#endif
715 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100716st:
wdenkde887eb2003-09-10 18:20:28 +0000717 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100718again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530719 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530720 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200721 &actlen, USB_CNTL_TIMEOUT*5);
722
wdenkde887eb2003-09-10 18:20:28 +0000723 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100724 if ((result < 0) && (retry < 1) &&
725 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530726 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000727 /* clear the STALL on the endpoint */
728 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
729 if (result >= 0 && (retry++ < 1))
730 /* do a retry */
731 goto again;
732 }
733 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530734 debug("usb_bulk_msg error status %ld\n",
735 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000736 usb_stor_BBB_reset(us);
737 return USB_STOR_TRANSPORT_FAILED;
738 }
739#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530740 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000741 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
742 printf("ptr[%d] %#x ", index, ptr[index]);
743 printf("\n");
744#endif
745 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530746 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000747 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
748 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530749 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530750 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000751 usb_stor_BBB_reset(us);
752 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530753 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530754 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000755 usb_stor_BBB_reset(us);
756 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530757 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530758 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000759 usb_stor_BBB_reset(us);
760 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530761 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530762 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000763 usb_stor_BBB_reset(us);
764 return USB_STOR_TRANSPORT_FAILED;
765 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530766 debug("transferred %dB instead of %ldB\n",
767 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000768 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530769 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530770 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000771 return USB_STOR_TRANSPORT_FAILED;
772 }
773
774 return result;
775}
776
Kim Phillipsb052b602012-10-29 13:34:32 +0000777static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000778{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100779 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000780 ccb *psrb;
781 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100782 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000783
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200784 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100785 status = USB_STOR_TRANSPORT_GOOD;
786 retry = 0;
787 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000788 /* issue the command */
789do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100790 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530791 debug("command / Data returned %d, status %lX\n",
792 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000793 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100794 if (us->protocol == US_PR_CBI) {
795 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000796 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100797 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530798 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000799 return status;
800 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100801 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
802 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
803 if (!us->ip_data) {
804 /* if the status is good, report it */
805 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530806 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000807 return status;
808 }
809 }
810 }
811 /* do we have to issue an auto request? */
812 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100813 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530814 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000815 us->transport_reset(us);
816 return USB_STOR_TRANSPORT_ERROR;
817 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100818 if ((us->protocol == US_PR_CBI) &&
819 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
820 (srb->cmd[0] == SCSI_INQUIRY))) {
821 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530822 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000823 return USB_STOR_TRANSPORT_GOOD;
824 }
825 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100826 memset(&psrb->cmd[0], 0, 12);
827 psrb->cmd[0] = SCSI_REQ_SENSE;
828 psrb->cmd[1] = srb->lun << 5;
829 psrb->cmd[4] = 18;
830 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200831 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100832 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000833 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100834 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530835 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000836 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100837 if (us->protocol == US_PR_CBI)
838 status = usb_stor_CBI_get_status(psrb, us);
839
840 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530841 debug(" AUTO REQUEST ERROR %ld\n",
842 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000843 return USB_STOR_TRANSPORT_ERROR;
844 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530845 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
846 srb->sense_buf[0], srb->sense_buf[2],
847 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000848 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100849 if ((srb->sense_buf[2] == 0) &&
850 (srb->sense_buf[12] == 0) &&
851 (srb->sense_buf[13] == 0)) {
852 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000853 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100854 }
855
wdenkaffae2b2002-08-17 09:36:01 +0000856 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100857 switch (srb->sense_buf[2]) {
858 case 0x01:
859 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000860 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000861 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100862 case 0x02:
863 /* Not Ready */
864 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
865 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
866 " 0x%02X (NOT READY)\n", srb->cmd[0],
867 srb->sense_buf[0], srb->sense_buf[2],
868 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000869 return USB_STOR_TRANSPORT_FAILED;
870 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000871 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000872 goto do_retry;
873 }
874 break;
875 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100876 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
877 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
878 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
879 srb->sense_buf[2], srb->sense_buf[12],
880 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000881 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100882 } else
wdenkde887eb2003-09-10 18:20:28 +0000883 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000884 break;
wdenkaffae2b2002-08-17 09:36:01 +0000885 }
886 return USB_STOR_TRANSPORT_FAILED;
887}
888
889
Michael Trimarchi956a4352008-12-10 15:52:06 +0100890static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000891{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100892 int retry, i;
893 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000894 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100895 memset(&srb->cmd[0], 0, 12);
896 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200897 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100898 srb->cmd[4] = 36;
899 srb->datalen = 36;
900 srb->cmdlen = 12;
901 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530902 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000904 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200905 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000906
Michael Trimarchi956a4352008-12-10 15:52:06 +0100907 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000908 printf("error in inquiry\n");
909 return -1;
910 }
911 return 0;
912}
913
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000915{
916 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000917
Michael Trimarchi956a4352008-12-10 15:52:06 +0100918 ptr = (char *)srb->pdata;
919 memset(&srb->cmd[0], 0, 12);
920 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200921 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100922 srb->cmd[4] = 18;
923 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200924 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100925 srb->cmdlen = 12;
926 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530927 debug("Request Sense returned %02X %02X %02X\n",
928 srb->sense_buf[2], srb->sense_buf[12],
929 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100930 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000931 return 0;
932}
933
Michael Trimarchi956a4352008-12-10 15:52:06 +0100934static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000935{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200936 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000937
wdenkaffae2b2002-08-17 09:36:01 +0000938 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100939 memset(&srb->cmd[0], 0, 12);
940 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200941 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100942 srb->datalen = 0;
943 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200944 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
945 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000946 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200947 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100948 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800949 /*
950 * Check the Key Code Qualifier, if it matches
951 * "Not Ready - medium not present"
952 * (the sense Key equals 0x2 and the ASC is 0x3a)
953 * return immediately as the medium being absent won't change
954 * unless there is a user action.
955 */
956 if ((srb->sense_buf[2] == 0x02) &&
957 (srb->sense_buf[12] == 0x3a))
958 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000959 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100960 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000961
wdenkaffae2b2002-08-17 09:36:01 +0000962 return -1;
963}
964
Michael Trimarchi956a4352008-12-10 15:52:06 +0100965static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000966{
967 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100968 /* XXX retries */
969 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000970 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100971 memset(&srb->cmd[0], 0, 12);
972 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200973 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100974 srb->datalen = 8;
975 srb->cmdlen = 12;
976 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000977 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000979
wdenkaffae2b2002-08-17 09:36:01 +0000980 return -1;
981}
982
Michael Trimarchi956a4352008-12-10 15:52:06 +0100983static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
984 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000985{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100986 memset(&srb->cmd[0], 0, 12);
987 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200988 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100989 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
990 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
991 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
992 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
993 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
994 srb->cmd[8] = (unsigned char) blocks & 0xff;
995 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530996 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000998}
999
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301000static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1001 unsigned short blocks)
1002{
1003 memset(&srb->cmd[0], 0, 12);
1004 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001005 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301006 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1007 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1008 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1009 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1010 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1011 srb->cmd[8] = (unsigned char) blocks & 0xff;
1012 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301013 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301014 return ss->transport(srb, ss);
1015}
1016
wdenkaffae2b2002-08-17 09:36:01 +00001017
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001018#ifdef CONFIG_USB_BIN_FIXUP
1019/*
1020 * Some USB storage devices queried for SCSI identification data respond with
1021 * binary strings, which if output to the console freeze the terminal. The
1022 * workaround is to modify the vendor and product strings read from such
1023 * device with proper values (as reported by 'usb info').
1024 *
1025 * Vendor and product length limits are taken from the definition of
1026 * block_dev_desc_t in include/part.h.
1027 */
1028static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1029 unsigned char vendor[],
1030 unsigned char product[]) {
1031 const unsigned char max_vendor_len = 40;
1032 const unsigned char max_product_len = 20;
1033 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001034 strncpy((char *)vendor, "SMSC", max_vendor_len);
1035 strncpy((char *)product, "Flash Media Cntrller",
1036 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001037 }
1038}
1039#endif /* CONFIG_USB_BIN_FIXUP */
1040
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001041unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001042 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001043{
Gabe Black7d077682012-10-12 14:26:07 +00001044 lbaint_t start, blks;
1045 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001046 unsigned short smallblks;
1047 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001048 struct us_data *ss;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049 int retry, i;
wdenk0e2874cb2004-03-02 14:05:39 +00001050 ccb *srb = &usb_ccb;
1051
1052 if (blkcnt == 0)
1053 return 0;
1054
1055 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001056 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301057 debug("\nusb_read: dev %d \n", device);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001058 dev = NULL;
1059 for (i = 0; i < USB_MAX_DEVICE; i++) {
1060 dev = usb_get_dev_index(i);
1061 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001062 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001063 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001064 break;
1065 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001066 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001067
1068 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 srb->lun = usb_dev_desc[device].lun;
1070 buf_addr = (unsigned long)buffer;
1071 start = blknr;
1072 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001073
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301074 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001075 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001076
wdenkaffae2b2002-08-17 09:36:01 +00001077 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001078 /* XXX need some comment here */
1079 retry = 2;
1080 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001081 if (blks > USB_MAX_XFER_BLK)
1082 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001083 else
1084 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001085retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001086 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001087 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001088 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1089 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001090 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301091 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001092 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001093 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001094 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001095 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001096 break;
1097 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001098 start += smallblks;
1099 blks -= smallblks;
1100 buf_addr += srb->datalen;
1101 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001102 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001103
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301104 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001105 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301106 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001107
wdenkaffae2b2002-08-17 09:36:01 +00001108 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001109 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001110 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001111 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001112}
1113
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001114unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001115 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301116{
Gabe Black7d077682012-10-12 14:26:07 +00001117 lbaint_t start, blks;
1118 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301119 unsigned short smallblks;
1120 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001121 struct us_data *ss;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301122 int retry, i;
1123 ccb *srb = &usb_ccb;
1124
1125 if (blkcnt == 0)
1126 return 0;
1127
1128 device &= 0xff;
1129 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301130 debug("\nusb_write: dev %d \n", device);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301131 dev = NULL;
1132 for (i = 0; i < USB_MAX_DEVICE; i++) {
1133 dev = usb_get_dev_index(i);
1134 if (dev == NULL)
1135 return 0;
1136 if (dev->devnum == usb_dev_desc[device].target)
1137 break;
1138 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001139 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301140
1141 usb_disable_asynch(1); /* asynch transfer not allowed */
1142
1143 srb->lun = usb_dev_desc[device].lun;
1144 buf_addr = (unsigned long)buffer;
1145 start = blknr;
1146 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301147
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301148 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001149 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301150
1151 do {
1152 /* If write fails retry for max retry count else
1153 * return with number of blocks written successfully.
1154 */
1155 retry = 2;
1156 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001157 if (blks > USB_MAX_XFER_BLK)
1158 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301159 else
1160 smallblks = (unsigned short) blks;
1161retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001162 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301163 usb_show_progress();
1164 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1165 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001166 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301167 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001168 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301169 if (retry--)
1170 goto retry_it;
1171 blkcnt -= blks;
1172 break;
1173 }
1174 start += smallblks;
1175 blks -= smallblks;
1176 buf_addr += srb->datalen;
1177 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001178 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301179
Simon Glassb43f7682014-10-15 04:38:38 -06001180 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1181 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301182
1183 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001184 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001185 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301186 return blkcnt;
1187
1188}
wdenkaffae2b2002-08-17 09:36:01 +00001189
1190/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001191int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1192 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001193{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001194 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001195 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301196 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001197 unsigned int flags = 0;
1198
1199 int protocol = 0;
1200 int subclass = 0;
1201
wdenkaffae2b2002-08-17 09:36:01 +00001202 /* let's examine the device now */
1203 iface = &dev->config.if_desc[ifnum];
1204
1205#if 0
1206 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301207 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001208 dev->descriptor.idProduct);
1209
1210 if ((dev->descriptor.idVendor) == 0x066b &&
1211 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301212 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001213 protocol = US_PR_CB;
1214 subclass = US_SC_UFI; /* an assumption */
1215 }
1216#endif
1217
1218 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001219 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1220 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1221 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001222 /* if it's not a mass storage, we go no further */
1223 return 0;
1224 }
1225
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001226 memset(ss, 0, sizeof(struct us_data));
1227
wdenkaffae2b2002-08-17 09:36:01 +00001228 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301229 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001230
1231 /* Initialize the us_data structure with some useful info */
1232 ss->flags = flags;
1233 ss->ifnum = ifnum;
1234 ss->pusb_dev = dev;
1235 ss->attention_done = 0;
1236
1237 /* If the device has subclass and protocol, then use that. Otherwise,
1238 * take data from the specific interface.
1239 */
1240 if (subclass) {
1241 ss->subclass = subclass;
1242 ss->protocol = protocol;
1243 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001244 ss->subclass = iface->desc.bInterfaceSubClass;
1245 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001246 }
1247
1248 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301249 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001250 switch (ss->protocol) {
1251 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301252 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001253 ss->transport = usb_stor_CB_transport;
1254 ss->transport_reset = usb_stor_CB_reset;
1255 break;
1256
1257 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301258 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001259 ss->transport = usb_stor_CB_transport;
1260 ss->transport_reset = usb_stor_CB_reset;
1261 break;
wdenkde887eb2003-09-10 18:20:28 +00001262 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301263 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001264 ss->transport = usb_stor_BBB_transport;
1265 ss->transport_reset = usb_stor_BBB_reset;
1266 break;
wdenkaffae2b2002-08-17 09:36:01 +00001267 default:
wdenk5f495752004-02-26 23:46:20 +00001268 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001269 return 0;
1270 break;
1271 }
1272
1273 /*
1274 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1275 * An optional interrupt is OK (necessary for CBI protocol).
1276 * We will ignore any others.
1277 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001278 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301279 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001280 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301281 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001282 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301283 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1284 ss->ep_in = ep_desc->bEndpointAddress &
1285 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001286 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001287 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301288 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001289 USB_ENDPOINT_NUMBER_MASK;
1290 }
1291
1292 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301293 if ((ep_desc->bmAttributes &
1294 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1295 ss->ep_int = ep_desc->bEndpointAddress &
1296 USB_ENDPOINT_NUMBER_MASK;
1297 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001298 }
1299 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301300 debug("Endpoints In %d Out %d Int %d\n",
1301 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001302
1303 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001304 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001305 !ss->ep_in || !ss->ep_out ||
1306 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301307 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001308 return 0;
1309 }
1310 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001311 /* We only handle certain protocols. Currently, these are
1312 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001313 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001314 */
wdenk5f495752004-02-26 23:46:20 +00001315 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1316 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001317 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001318 return 0;
1319 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001320 if (ss->ep_int) {
1321 /* we had found an interrupt endpoint, prepare irq pipe
1322 * set up the IRQ pipe and handler
1323 */
wdenkaffae2b2002-08-17 09:36:01 +00001324 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1325 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1326 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001327 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001328 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001329 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001330 return 1;
1331}
1332
Michael Trimarchi956a4352008-12-10 15:52:06 +01001333int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1334 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001335{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001336 unsigned char perq, modi;
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301337 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1338 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001339 unsigned long *capacity, *blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001340 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001341
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001342 pccb->pdata = usb_stor_buf;
1343
1344 dev_desc->target = dev->devnum;
1345 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301346 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001347
Michael Trimarchi956a4352008-12-10 15:52:06 +01001348 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001349 return -1;
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001350
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001351 perq = usb_stor_buf[0];
1352 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001353
1354 if ((perq & 0x1f) == 0x1f) {
1355 /* skip unknown devices */
1356 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001357 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001358 if ((modi&0x80) == 0x80) {
1359 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001360 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001361 }
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301362 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1363 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1364 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001365 dev_desc->vendor[8] = 0;
1366 dev_desc->product[16] = 0;
1367 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001368#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001369 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1370 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001371#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301372 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1373 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001374 if (usb_test_unit_ready(pccb, ss)) {
1375 printf("Device NOT ready\n"
1376 " Request Sense returned %02X %02X %02X\n",
1377 pccb->sense_buf[2], pccb->sense_buf[12],
1378 pccb->sense_buf[13]);
1379 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001380 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001381 return 1;
1382 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001383 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001384 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001385 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001386 memset(pccb->pdata, 0, 8);
1387 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001388 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001389 cap[0] = 2880;
1390 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001391 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001392 ss->flags &= ~USB_READY;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301393 debug("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001394#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001395 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1396 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001397#endif
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001398 cap[0] = cpu_to_be32(cap[0]);
1399 cap[1] = cpu_to_be32(cap[1]);
1400
wdenkde887eb2003-09-10 18:20:28 +00001401 /* this assumes bigendian! */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001402 cap[0] += 1;
1403 capacity = &cap[0];
1404 blksz = &cap[1];
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301405 debug("Capacity = 0x%lx, blocksz = 0x%lx\n", *capacity, *blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001406 dev_desc->lba = *capacity;
1407 dev_desc->blksz = *blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001408 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001409 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301410 debug(" address %d\n", dev_desc->target);
1411 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001412
1413 init_part(dev_desc);
1414
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301415 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001416 return 1;
1417}