blob: 6ac358d5e2be3ca3acce9dc7e5957ed483943922 [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>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020036#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000037#include <asm/processor.h>
38
Grant Likelyffc2dd72007-02-20 09:04:34 +010039#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000040#include <usb.h>
41
wdenk5f495752004-02-26 23:46:20 +000042#undef BBB_COMDAT_TRACE
43#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000044
wdenkaffae2b2002-08-17 09:36:01 +000045#include <scsi.h>
46/* direction table -- this indicates the direction of the data
47 * transfer for each command code -- a 1 indicates input
48 */
Mike Frysinger165522b2010-10-20 07:16:04 -040049static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000050 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
51 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
54};
55#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
56
Puneet Saxena6c9bb602012-04-03 14:56:06 +053057static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
wdenkaffae2b2002-08-17 09:36:01 +000058
59/*
60 * CBI style
61 */
62
63#define US_CBI_ADSC 0
64
wdenkde887eb2003-09-10 18:20:28 +000065/*
66 * BULK only
67 */
68#define US_BBB_RESET 0xff
69#define US_BBB_GET_MAX_LUN 0xfe
70
71/* Command Block Wrapper */
72typedef struct {
73 __u32 dCBWSignature;
74# define CBWSIGNATURE 0x43425355
75 __u32 dCBWTag;
76 __u32 dCBWDataTransferLength;
77 __u8 bCBWFlags;
78# define CBWFLAGS_OUT 0x00
79# define CBWFLAGS_IN 0x80
80 __u8 bCBWLUN;
81 __u8 bCDBLength;
82# define CBWCDBLENGTH 16
83 __u8 CBWCDB[CBWCDBLENGTH];
84} umass_bbb_cbw_t;
wdenk5f495752004-02-26 23:46:20 +000085#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchi956a4352008-12-10 15:52:06 +010086static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000087
88/* Command Status Wrapper */
89typedef struct {
90 __u32 dCSWSignature;
91# define CSWSIGNATURE 0x53425355
92 __u32 dCSWTag;
93 __u32 dCSWDataResidue;
94 __u8 bCSWStatus;
95# define CSWSTATUS_GOOD 0x0
wdenk5f495752004-02-26 23:46:20 +000096# define CSWSTATUS_FAILED 0x1
wdenkde887eb2003-09-10 18:20:28 +000097# define CSWSTATUS_PHASE 0x2
98} umass_bbb_csw_t;
wdenk5f495752004-02-26 23:46:20 +000099#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000100
101#define USB_MAX_STOR_DEV 5
Michael Trimarchi956a4352008-12-10 15:52:06 +0100102static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000103
104static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
105
106struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100107typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
108typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000109
110struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100111 struct usb_device *pusb_dev; /* this usb_device */
112
113 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200114# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +0100115 unsigned char ifnum; /* interface number */
116 unsigned char ep_in; /* in endpoint */
117 unsigned char ep_out; /* out ....... */
118 unsigned char ep_int; /* interrupt . */
119 unsigned char subclass; /* as in overview */
120 unsigned char protocol; /* .............. */
121 unsigned char attention_done; /* force attn on first cmd */
122 unsigned short ip_data; /* interrupt data */
123 int action; /* what to do */
124 int ip_wanted; /* needed */
125 int *irq_handle; /* for USB int requests */
126 unsigned int irqpipe; /* pipe for release_irq */
127 unsigned char irqmaxp; /* max packed for irq Pipe */
128 unsigned char irqinterval; /* Intervall for IRQ Pipe */
129 ccb *srb; /* current srb */
130 trans_reset transport_reset; /* reset routine */
131 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000132};
133
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200134#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000135/*
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200136 * The U-Boot EHCI driver can handle any transfer length as long as there is
137 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
138 * limited to 65535 blocks.
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000139 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200140#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200141#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200142#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200143#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000144
wdenkaffae2b2002-08-17 09:36:01 +0000145static struct us_data usb_stor[USB_MAX_STOR_DEV];
146
147
wdenk5f495752004-02-26 23:46:20 +0000148#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000149#define USB_STOR_TRANSPORT_FAILED -1
150#define USB_STOR_TRANSPORT_ERROR -2
151
Michael Trimarchi956a4352008-12-10 15:52:06 +0100152int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
153 block_dev_desc_t *dev_desc);
154int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
155 struct us_data *ss);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200156unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000157 lbaint_t blkcnt, void *buffer);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200158unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000159 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000160struct usb_device * usb_get_dev_index(int index);
161void uhci_show_temp_int_td(void);
162
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000163#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000164block_dev_desc_t *usb_stor_get_dev(int index)
165{
Kim B. Heino300ea512010-03-12 15:46:56 +0200166 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000167}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000168#endif
wdenkaffae2b2002-08-17 09:36:01 +0000169
Kim Phillipsb052b602012-10-29 13:34:32 +0000170static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000171{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200172 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000173}
174
Michael Trimarchi956a4352008-12-10 15:52:06 +0100175/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200176 * show info on storage devices; 'usb start/init' must be invoked earlier
177 * as we only retrieve structures populated during devices initialization
178 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100179int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200180{
181 int i;
182
Aras Vaichas7ede1862008-03-25 12:09:07 +1100183 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200184 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100185 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200186 dev_print(&usb_dev_desc[i]);
187 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100188 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100189 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700190
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100191 printf("No storage devices, perhaps not 'usb start'ed..?\n");
192 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200193}
194
Ludovic Courtès134396c2010-10-05 22:04:26 +0200195static unsigned int usb_get_max_lun(struct us_data *us)
196{
197 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530198 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200199 len = usb_control_msg(us->pusb_dev,
200 usb_rcvctrlpipe(us->pusb_dev, 0),
201 US_BBB_GET_MAX_LUN,
202 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
203 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530204 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200205 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530206 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530207 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200208}
209
Michael Trimarchi956a4352008-12-10 15:52:06 +0100210/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200211 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000212 * to the user if mode = 1
213 * returns current device or -1 if no
214 */
215int usb_stor_scan(int mode)
216{
217 unsigned char i;
218 struct usb_device *dev;
219
Michael Trimarchi956a4352008-12-10 15:52:06 +0100220 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200221 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100222
wdenkaffae2b2002-08-17 09:36:01 +0000223 usb_disable_asynch(1); /* asynch transfer not allowed */
224
Michael Trimarchi956a4352008-12-10 15:52:06 +0100225 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
226 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100227 usb_dev_desc[i].if_type = IF_TYPE_USB;
228 usb_dev_desc[i].dev = i;
229 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200230 usb_dev_desc[i].target = 0xff;
231 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100232 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530233 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000234 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200235
Michael Trimarchi956a4352008-12-10 15:52:06 +0100236 usb_max_devs = 0;
237 for (i = 0; i < USB_MAX_DEVICE; i++) {
238 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530239 debug("i=%d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100240 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100241 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100242
243 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès134396c2010-10-05 22:04:26 +0200244 /* OK, it's a storage device. Iterate over its LUNs
245 * and populate `usb_dev_desc'.
Michael Trimarchi956a4352008-12-10 15:52:06 +0100246 */
Ludovic Courtès134396c2010-10-05 22:04:26 +0200247 int lun, max_lun, start = usb_max_devs;
248
249 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
250 for (lun = 0;
251 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
252 lun++) {
253 usb_dev_desc[usb_max_devs].lun = lun;
254 if (usb_stor_get_info(dev, &usb_stor[start],
Vivek Gautam23cbd292013-04-12 16:34:34 +0530255 &usb_dev_desc[usb_max_devs]) == 1) {
256 usb_max_devs++;
257 }
Ludovic Courtès134396c2010-10-05 22:04:26 +0200258 }
259 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100260 /* if storage device */
261 if (usb_max_devs == USB_MAX_STOR_DEV) {
262 printf("max USB Storage Device reached: %d stopping\n",
263 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000264 break;
265 }
266 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200267
wdenkaffae2b2002-08-17 09:36:01 +0000268 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200269 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100270 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000271 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100272 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000273}
274
275static int usb_stor_irq(struct usb_device *dev)
276{
277 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100278 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000279
Michael Trimarchi956a4352008-12-10 15:52:06 +0100280 if (us->ip_wanted)
281 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000282 return 0;
283}
284
285
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530286#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000287
Michael Trimarchi956a4352008-12-10 15:52:06 +0100288static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000289{
290 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100291 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
292 for (i = 0; i < 12; i++)
293 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000294 printf("\n");
295}
296
297static void display_int_status(unsigned long tmp)
298{
299 printf("Status: %s %s %s %s %s %s %s\n",
300 (tmp & USB_ST_ACTIVE) ? "Active" : "",
301 (tmp & USB_ST_STALLED) ? "Stalled" : "",
302 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
303 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
304 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
305 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
306 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
307}
308#endif
309/***********************************************************************
310 * Data transfer routines
311 ***********************************************************************/
312
313static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
314{
315 int max_size;
316 int this_xfer;
317 int result;
318 int partial;
319 int maxtry;
320 int stat;
321
322 /* determine the maximum packet size for these transfers */
323 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
324
325 /* while we have data left to transfer */
326 while (length) {
327
328 /* calculate how long this will be -- maximum or a remainder */
329 this_xfer = length > max_size ? max_size : length;
330 length -= this_xfer;
331
332 /* setup the retry counter */
333 maxtry = 10;
334
335 /* set up the transfer loop */
336 do {
337 /* transfer the data */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530338 debug("Bulk xfer 0x%x(%d) try #%d\n",
339 (unsigned int)buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000340 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100341 this_xfer, &partial,
342 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530343 debug("bulk_msg returned %d xferred %d/%d\n",
344 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100345 if (us->pusb_dev->status != 0) {
346 /* if we stall, we need to clear it before
347 * we go on
348 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530349#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000350 display_int_status(us->pusb_dev->status);
351#endif
352 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530353 debug("stalled ->clearing endpoint" \
354 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000355 stat = us->pusb_dev->status;
356 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100357 us->pusb_dev->status = stat;
358 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530359 debug("bulk transferred" \
360 "with error %lX," \
361 " but data ok\n",
362 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000363 return 0;
364 }
365 else
366 return result;
367 }
368 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530369 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000370 return result;
371 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530372 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100373 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530374 debug(" %ld, but data ok\n",
375 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000376 return 0;
377 }
378 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530379 debug(" %ld, data %d\n",
380 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000381 if (!maxtry--)
382 return result;
383 }
384 /* update to show what data was transferred */
385 this_xfer -= partial;
386 buf += partial;
387 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100388 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000389 }
390
391 /* if we get here, we're done and successful */
392 return 0;
393}
394
wdenkde887eb2003-09-10 18:20:28 +0000395static int usb_stor_BBB_reset(struct us_data *us)
396{
397 int result;
398 unsigned int pipe;
399
400 /*
401 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
402 *
403 * For Reset Recovery the host shall issue in the following order:
404 * a) a Bulk-Only Mass Storage Reset
405 * b) a Clear Feature HALT to the Bulk-In endpoint
406 * c) a Clear Feature HALT to the Bulk-Out endpoint
407 *
408 * This is done in 3 steps.
409 *
410 * If the reset doesn't succeed, the device should be port reset.
411 *
412 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
413 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530414 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100415 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
416 US_BBB_RESET,
417 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000418 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200419
Michael Trimarchi956a4352008-12-10 15:52:06 +0100420 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530421 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000422 return -1;
423 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200424
wdenkde887eb2003-09-10 18:20:28 +0000425 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000426 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530427 debug("BBB_reset result %d: status %lX reset\n",
428 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000429 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
430 result = usb_clear_halt(us->pusb_dev, pipe);
431 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000432 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530433 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
434 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000435 /* long wait for reset */
436 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
437 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000438 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530439 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
440 result, us->pusb_dev->status);
441 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000442 return 0;
443}
444
wdenkaffae2b2002-08-17 09:36:01 +0000445/* FIXME: this reset function doesn't really reset the port, and it
446 * should. Actually it should probably do what it's doing here, and
447 * reset the port physically
448 */
449static int usb_stor_CB_reset(struct us_data *us)
450{
451 unsigned char cmd[12];
452 int result;
453
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530454 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100455 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000456 cmd[0] = SCSI_SEND_DIAG;
457 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100458 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
459 US_CBI_ADSC,
460 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
461 0, us->ifnum, cmd, sizeof(cmd),
462 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000463
464 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000465 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530466 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
467 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000468 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
469 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
470
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530471 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000472 return 0;
473}
474
wdenkde887eb2003-09-10 18:20:28 +0000475/*
476 * Set up the command for a BBB device. Note that the actual SCSI
477 * command is copied into cbw.CBWCDB.
478 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000479static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000480{
481 int result;
482 int actlen;
483 int dir_in;
484 unsigned int pipe;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530485 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000486
487 dir_in = US_DIRECTION(srb->cmd[0]);
488
489#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530490 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100491 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
492 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000493 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100494 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000495 printf("cmd[%d] %#x ", result, srb->cmd[result]);
496 printf("\n");
497 }
498#endif
499 /* sanity checks */
500 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530501 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000502 return -1;
503 }
504
505 /* always OUT to the ep */
506 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
507
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530508 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
509 cbw->dCBWTag = cpu_to_le32(CBWTag++);
510 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
511 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
512 cbw->bCBWLUN = srb->lun;
513 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000514 /* copy the command data into the CBW command data buffer */
515 /* DST SRC LEN!!! */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530516 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
517 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100518 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000519 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530520 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000521 return result;
522}
523
wdenkaffae2b2002-08-17 09:36:01 +0000524/* FIXME: we also need a CBI_command which sets up the completion
525 * interrupt, and waits for it
526 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000527static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000528{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200529 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100530 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000531 unsigned int pipe;
532 unsigned long status;
533
Michael Trimarchi956a4352008-12-10 15:52:06 +0100534 retry = 5;
535 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000536
Michael Trimarchi956a4352008-12-10 15:52:06 +0100537 if (dir_in)
538 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
539 else
540 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
541
542 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530543 debug("CBI gets a command: Try %d\n", 5 - retry);
544#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000545 usb_show_srb(srb);
546#endif
547 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100548 result = usb_control_msg(us->pusb_dev,
549 usb_sndctrlpipe(us->pusb_dev , 0),
550 US_CBI_ADSC,
551 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000552 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100553 srb->cmd, srb->cmdlen,
554 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530555 debug("CB_transport: control msg returned %d, status %lX\n",
556 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000557 /* check the return code for the command */
558 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100559 if (us->pusb_dev->status & USB_ST_STALLED) {
560 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530561 debug(" stall during command found," \
562 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100563 usb_clear_halt(us->pusb_dev,
564 usb_sndctrlpipe(us->pusb_dev, 0));
565 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000566 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530567 debug(" error during command %02X" \
568 " Stat = %lX\n", srb->cmd[0],
569 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000570 return result;
571 }
572 /* transfer the data payload for this command, if one exists*/
573
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530574 debug("CB_transport: control msg returned %d," \
575 " direction is %s to go 0x%lx\n", result,
576 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000577 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100578 result = us_one_transfer(us, pipe, (char *)srb->pdata,
579 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530580 debug("CBI attempted to transfer data," \
581 " result is %d status %lX, len %d\n",
582 result, us->pusb_dev->status,
583 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100584 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000585 break;
586 } /* if (srb->datalen) */
587 else
588 break;
589 }
590 /* return result */
591
592 return result;
593}
594
595
Kim Phillipsb052b602012-10-29 13:34:32 +0000596static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000597{
598 int timeout;
599
wdenk5f495752004-02-26 23:46:20 +0000600 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100601 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000602 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
603 timeout = 1000;
604 while (timeout--) {
Kim Phillipsb052b602012-10-29 13:34:32 +0000605 if ((volatile int *) us->ip_wanted == NULL)
wdenkaffae2b2002-08-17 09:36:01 +0000606 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000607 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000608 }
609 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100610 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000611 us->ip_wanted = 0;
612 return USB_STOR_TRANSPORT_ERROR;
613 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530614 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
615 us->ip_data, us->pusb_dev->irq_act_len,
616 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000617 /* UFI gives us ASC and ASCQ, like a request sense */
618 if (us->subclass == US_SC_UFI) {
619 if (srb->cmd[0] == SCSI_REQ_SENSE ||
620 srb->cmd[0] == SCSI_INQUIRY)
621 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000622 else if (us->ip_data)
623 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000624 else
wdenk5f495752004-02-26 23:46:20 +0000625 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000626 }
627 /* otherwise, we interpret the data normally */
628 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000629 case 0x0001:
630 return USB_STOR_TRANSPORT_GOOD;
631 case 0x0002:
632 return USB_STOR_TRANSPORT_FAILED;
633 default:
634 return USB_STOR_TRANSPORT_ERROR;
635 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000636 return USB_STOR_TRANSPORT_ERROR;
637}
638
639#define USB_TRANSPORT_UNKNOWN_RETRY 5
640#define USB_TRANSPORT_NOT_READY_RETRY 10
641
wdenkde887eb2003-09-10 18:20:28 +0000642/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000643static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000644{
645 int result;
646
647 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100648 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000649 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000650 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000651 return result;
652}
653
Kim Phillipsb052b602012-10-29 13:34:32 +0000654static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000655{
656 int result, retry;
657 int dir_in;
658 int actlen, data_actlen;
659 unsigned int pipe, pipein, pipeout;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530660 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000661#ifdef BBB_XPORT_TRACE
662 unsigned char *ptr;
663 int index;
664#endif
665
666 dir_in = US_DIRECTION(srb->cmd[0]);
667
668 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530669 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000670 result = usb_stor_BBB_comdat(srb, us);
671 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530672 debug("failed to send CBW status %ld\n",
673 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000674 usb_stor_BBB_reset(us);
675 return USB_STOR_TRANSPORT_FAILED;
676 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200677 if (!(us->flags & USB_READY))
678 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000679 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
680 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
681 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000682 data_actlen = 0;
683 /* no data, go immediately to the STATUS phase */
684 if (srb->datalen == 0)
685 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530686 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000687 if (dir_in)
688 pipe = pipein;
689 else
690 pipe = pipeout;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100691 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
692 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000693 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100694 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530695 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000696 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100697 result = usb_stor_BBB_clear_endpt_stall(us,
698 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000699 if (result >= 0)
700 /* continue on to STATUS phase */
701 goto st;
702 }
703 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530704 debug("usb_bulk_msg error status %ld\n",
705 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000706 usb_stor_BBB_reset(us);
707 return USB_STOR_TRANSPORT_FAILED;
708 }
709#ifdef BBB_XPORT_TRACE
710 for (index = 0; index < data_actlen; index++)
711 printf("pdata[%d] %#x ", index, srb->pdata[index]);
712 printf("\n");
713#endif
714 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100715st:
wdenkde887eb2003-09-10 18:20:28 +0000716 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100717again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530718 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530719 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200720 &actlen, USB_CNTL_TIMEOUT*5);
721
wdenkde887eb2003-09-10 18:20:28 +0000722 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100723 if ((result < 0) && (retry < 1) &&
724 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530725 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000726 /* clear the STALL on the endpoint */
727 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
728 if (result >= 0 && (retry++ < 1))
729 /* do a retry */
730 goto again;
731 }
732 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530733 debug("usb_bulk_msg error status %ld\n",
734 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000735 usb_stor_BBB_reset(us);
736 return USB_STOR_TRANSPORT_FAILED;
737 }
738#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530739 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000740 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
741 printf("ptr[%d] %#x ", index, ptr[index]);
742 printf("\n");
743#endif
744 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530745 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000746 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
747 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530748 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530749 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000750 usb_stor_BBB_reset(us);
751 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530752 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530753 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000754 usb_stor_BBB_reset(us);
755 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530756 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530757 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000758 usb_stor_BBB_reset(us);
759 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530760 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530761 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000762 usb_stor_BBB_reset(us);
763 return USB_STOR_TRANSPORT_FAILED;
764 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530765 debug("transferred %dB instead of %ldB\n",
766 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000767 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530768 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530769 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000770 return USB_STOR_TRANSPORT_FAILED;
771 }
772
773 return result;
774}
775
Kim Phillipsb052b602012-10-29 13:34:32 +0000776static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000777{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100778 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000779 ccb *psrb;
780 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100781 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000782
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200783 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100784 status = USB_STOR_TRANSPORT_GOOD;
785 retry = 0;
786 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000787 /* issue the command */
788do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100789 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530790 debug("command / Data returned %d, status %lX\n",
791 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000792 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100793 if (us->protocol == US_PR_CBI) {
794 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000795 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100796 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530797 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000798 return status;
799 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100800 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
801 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
802 if (!us->ip_data) {
803 /* if the status is good, report it */
804 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530805 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000806 return status;
807 }
808 }
809 }
810 /* do we have to issue an auto request? */
811 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100812 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530813 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000814 us->transport_reset(us);
815 return USB_STOR_TRANSPORT_ERROR;
816 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100817 if ((us->protocol == US_PR_CBI) &&
818 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
819 (srb->cmd[0] == SCSI_INQUIRY))) {
820 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530821 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000822 return USB_STOR_TRANSPORT_GOOD;
823 }
824 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100825 memset(&psrb->cmd[0], 0, 12);
826 psrb->cmd[0] = SCSI_REQ_SENSE;
827 psrb->cmd[1] = srb->lun << 5;
828 psrb->cmd[4] = 18;
829 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200830 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100831 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000832 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100833 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530834 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000835 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100836 if (us->protocol == US_PR_CBI)
837 status = usb_stor_CBI_get_status(psrb, us);
838
839 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530840 debug(" AUTO REQUEST ERROR %ld\n",
841 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000842 return USB_STOR_TRANSPORT_ERROR;
843 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530844 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
845 srb->sense_buf[0], srb->sense_buf[2],
846 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 if ((srb->sense_buf[2] == 0) &&
849 (srb->sense_buf[12] == 0) &&
850 (srb->sense_buf[13] == 0)) {
851 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000852 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100853 }
854
wdenkaffae2b2002-08-17 09:36:01 +0000855 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100856 switch (srb->sense_buf[2]) {
857 case 0x01:
858 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000859 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000860 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100861 case 0x02:
862 /* Not Ready */
863 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
864 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
865 " 0x%02X (NOT READY)\n", srb->cmd[0],
866 srb->sense_buf[0], srb->sense_buf[2],
867 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000868 return USB_STOR_TRANSPORT_FAILED;
869 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000870 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000871 goto do_retry;
872 }
873 break;
874 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100875 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
876 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
877 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
878 srb->sense_buf[2], srb->sense_buf[12],
879 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000880 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 } else
wdenkde887eb2003-09-10 18:20:28 +0000882 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000883 break;
wdenkaffae2b2002-08-17 09:36:01 +0000884 }
885 return USB_STOR_TRANSPORT_FAILED;
886}
887
888
Michael Trimarchi956a4352008-12-10 15:52:06 +0100889static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000890{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100891 int retry, i;
892 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000893 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100894 memset(&srb->cmd[0], 0, 12);
895 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200896 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100897 srb->cmd[4] = 36;
898 srb->datalen = 36;
899 srb->cmdlen = 12;
900 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530901 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100902 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000903 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200904 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000905
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000907 printf("error in inquiry\n");
908 return -1;
909 }
910 return 0;
911}
912
Michael Trimarchi956a4352008-12-10 15:52:06 +0100913static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000914{
915 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000916
Michael Trimarchi956a4352008-12-10 15:52:06 +0100917 ptr = (char *)srb->pdata;
918 memset(&srb->cmd[0], 0, 12);
919 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200920 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100921 srb->cmd[4] = 18;
922 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200923 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100924 srb->cmdlen = 12;
925 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530926 debug("Request Sense returned %02X %02X %02X\n",
927 srb->sense_buf[2], srb->sense_buf[12],
928 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100929 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000930 return 0;
931}
932
Michael Trimarchi956a4352008-12-10 15:52:06 +0100933static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000934{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200935 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000936
wdenkaffae2b2002-08-17 09:36:01 +0000937 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100938 memset(&srb->cmd[0], 0, 12);
939 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200940 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100941 srb->datalen = 0;
942 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200943 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
944 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000945 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200946 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100947 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800948 /*
949 * Check the Key Code Qualifier, if it matches
950 * "Not Ready - medium not present"
951 * (the sense Key equals 0x2 and the ASC is 0x3a)
952 * return immediately as the medium being absent won't change
953 * unless there is a user action.
954 */
955 if ((srb->sense_buf[2] == 0x02) &&
956 (srb->sense_buf[12] == 0x3a))
957 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000958 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100959 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000960
wdenkaffae2b2002-08-17 09:36:01 +0000961 return -1;
962}
963
Michael Trimarchi956a4352008-12-10 15:52:06 +0100964static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000965{
966 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100967 /* XXX retries */
968 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000969 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100970 memset(&srb->cmd[0], 0, 12);
971 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200972 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100973 srb->datalen = 8;
974 srb->cmdlen = 12;
975 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000976 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100977 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000978
wdenkaffae2b2002-08-17 09:36:01 +0000979 return -1;
980}
981
Michael Trimarchi956a4352008-12-10 15:52:06 +0100982static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
983 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000984{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100985 memset(&srb->cmd[0], 0, 12);
986 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200987 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100988 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
989 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
990 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
991 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
992 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
993 srb->cmd[8] = (unsigned char) blocks & 0xff;
994 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530995 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100996 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000997}
998
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530999static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1000 unsigned short blocks)
1001{
1002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301005 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1006 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1007 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1008 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1009 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1010 srb->cmd[8] = (unsigned char) blocks & 0xff;
1011 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301012 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301013 return ss->transport(srb, ss);
1014}
1015
wdenkaffae2b2002-08-17 09:36:01 +00001016
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001017#ifdef CONFIG_USB_BIN_FIXUP
1018/*
1019 * Some USB storage devices queried for SCSI identification data respond with
1020 * binary strings, which if output to the console freeze the terminal. The
1021 * workaround is to modify the vendor and product strings read from such
1022 * device with proper values (as reported by 'usb info').
1023 *
1024 * Vendor and product length limits are taken from the definition of
1025 * block_dev_desc_t in include/part.h.
1026 */
1027static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1028 unsigned char vendor[],
1029 unsigned char product[]) {
1030 const unsigned char max_vendor_len = 40;
1031 const unsigned char max_product_len = 20;
1032 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001033 strncpy((char *)vendor, "SMSC", max_vendor_len);
1034 strncpy((char *)product, "Flash Media Cntrller",
1035 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001036 }
1037}
1038#endif /* CONFIG_USB_BIN_FIXUP */
1039
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001040unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001041 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001042{
Gabe Black7d077682012-10-12 14:26:07 +00001043 lbaint_t start, blks;
1044 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001045 unsigned short smallblks;
1046 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001047 struct us_data *ss;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001048 int retry, i;
wdenk0e2874cb2004-03-02 14:05:39 +00001049 ccb *srb = &usb_ccb;
1050
1051 if (blkcnt == 0)
1052 return 0;
1053
1054 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001055 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301056 debug("\nusb_read: dev %d \n", device);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001057 dev = NULL;
1058 for (i = 0; i < USB_MAX_DEVICE; i++) {
1059 dev = usb_get_dev_index(i);
1060 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001061 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001062 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001063 break;
1064 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001065 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001066
1067 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001068 srb->lun = usb_dev_desc[device].lun;
1069 buf_addr = (unsigned long)buffer;
1070 start = blknr;
1071 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301073 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
1074 " buffer %lx\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001075
wdenkaffae2b2002-08-17 09:36:01 +00001076 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001077 /* XXX need some comment here */
1078 retry = 2;
1079 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001080 if (blks > USB_MAX_XFER_BLK)
1081 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001082 else
1083 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001084retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001085 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001086 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001087 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1088 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001089 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301090 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001091 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001092 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001093 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001094 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001095 break;
1096 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001097 start += smallblks;
1098 blks -= smallblks;
1099 buf_addr += srb->datalen;
1100 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001101 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001102
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301103 debug("usb_read: end startblk " LBAF
1104 ", blccnt %x buffer %lx\n",
1105 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001106
wdenkaffae2b2002-08-17 09:36:01 +00001107 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001108 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001109 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001110 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001111}
1112
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001113unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001114 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301115{
Gabe Black7d077682012-10-12 14:26:07 +00001116 lbaint_t start, blks;
1117 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301118 unsigned short smallblks;
1119 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001120 struct us_data *ss;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301121 int retry, i;
1122 ccb *srb = &usb_ccb;
1123
1124 if (blkcnt == 0)
1125 return 0;
1126
1127 device &= 0xff;
1128 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301129 debug("\nusb_write: dev %d \n", device);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301130 dev = NULL;
1131 for (i = 0; i < USB_MAX_DEVICE; i++) {
1132 dev = usb_get_dev_index(i);
1133 if (dev == NULL)
1134 return 0;
1135 if (dev->devnum == usb_dev_desc[device].target)
1136 break;
1137 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001138 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301139
1140 usb_disable_asynch(1); /* asynch transfer not allowed */
1141
1142 srb->lun = usb_dev_desc[device].lun;
1143 buf_addr = (unsigned long)buffer;
1144 start = blknr;
1145 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301146
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301147 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
1148 " buffer %lx\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301149
1150 do {
1151 /* If write fails retry for max retry count else
1152 * return with number of blocks written successfully.
1153 */
1154 retry = 2;
1155 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001156 if (blks > USB_MAX_XFER_BLK)
1157 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301158 else
1159 smallblks = (unsigned short) blks;
1160retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001161 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301162 usb_show_progress();
1163 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1164 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001165 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301166 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001167 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301168 if (retry--)
1169 goto retry_it;
1170 blkcnt -= blks;
1171 break;
1172 }
1173 start += smallblks;
1174 blks -= smallblks;
1175 buf_addr += srb->datalen;
1176 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001177 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301178
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301179 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1180 start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301181
1182 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001183 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001184 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301185 return blkcnt;
1186
1187}
wdenkaffae2b2002-08-17 09:36:01 +00001188
1189/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001190int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1191 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001192{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001193 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001194 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301195 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001196 unsigned int flags = 0;
1197
1198 int protocol = 0;
1199 int subclass = 0;
1200
wdenkaffae2b2002-08-17 09:36:01 +00001201 /* let's examine the device now */
1202 iface = &dev->config.if_desc[ifnum];
1203
1204#if 0
1205 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301206 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001207 dev->descriptor.idProduct);
1208
1209 if ((dev->descriptor.idVendor) == 0x066b &&
1210 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301211 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001212 protocol = US_PR_CB;
1213 subclass = US_SC_UFI; /* an assumption */
1214 }
1215#endif
1216
1217 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001218 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1219 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1220 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001221 /* if it's not a mass storage, we go no further */
1222 return 0;
1223 }
1224
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001225 memset(ss, 0, sizeof(struct us_data));
1226
wdenkaffae2b2002-08-17 09:36:01 +00001227 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301228 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001229
1230 /* Initialize the us_data structure with some useful info */
1231 ss->flags = flags;
1232 ss->ifnum = ifnum;
1233 ss->pusb_dev = dev;
1234 ss->attention_done = 0;
1235
1236 /* If the device has subclass and protocol, then use that. Otherwise,
1237 * take data from the specific interface.
1238 */
1239 if (subclass) {
1240 ss->subclass = subclass;
1241 ss->protocol = protocol;
1242 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001243 ss->subclass = iface->desc.bInterfaceSubClass;
1244 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001245 }
1246
1247 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301248 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001249 switch (ss->protocol) {
1250 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301251 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001252 ss->transport = usb_stor_CB_transport;
1253 ss->transport_reset = usb_stor_CB_reset;
1254 break;
1255
1256 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301257 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001258 ss->transport = usb_stor_CB_transport;
1259 ss->transport_reset = usb_stor_CB_reset;
1260 break;
wdenkde887eb2003-09-10 18:20:28 +00001261 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301262 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001263 ss->transport = usb_stor_BBB_transport;
1264 ss->transport_reset = usb_stor_BBB_reset;
1265 break;
wdenkaffae2b2002-08-17 09:36:01 +00001266 default:
wdenk5f495752004-02-26 23:46:20 +00001267 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001268 return 0;
1269 break;
1270 }
1271
1272 /*
1273 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1274 * An optional interrupt is OK (necessary for CBI protocol).
1275 * We will ignore any others.
1276 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001277 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301278 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001279 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301280 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001281 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301282 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1283 ss->ep_in = ep_desc->bEndpointAddress &
1284 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001285 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001286 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301287 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001288 USB_ENDPOINT_NUMBER_MASK;
1289 }
1290
1291 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301292 if ((ep_desc->bmAttributes &
1293 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1294 ss->ep_int = ep_desc->bEndpointAddress &
1295 USB_ENDPOINT_NUMBER_MASK;
1296 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001297 }
1298 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301299 debug("Endpoints In %d Out %d Int %d\n",
1300 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001301
1302 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001303 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001304 !ss->ep_in || !ss->ep_out ||
1305 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301306 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001307 return 0;
1308 }
1309 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001310 /* We only handle certain protocols. Currently, these are
1311 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001312 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001313 */
wdenk5f495752004-02-26 23:46:20 +00001314 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1315 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001316 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001317 return 0;
1318 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001319 if (ss->ep_int) {
1320 /* we had found an interrupt endpoint, prepare irq pipe
1321 * set up the IRQ pipe and handler
1322 */
wdenkaffae2b2002-08-17 09:36:01 +00001323 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1324 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1325 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001326 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001327 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001328 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001329 return 1;
1330}
1331
Michael Trimarchi956a4352008-12-10 15:52:06 +01001332int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1333 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001334{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001335 unsigned char perq, modi;
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301336 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1337 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001338 unsigned long *capacity, *blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001339 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001340
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001341 pccb->pdata = usb_stor_buf;
1342
1343 dev_desc->target = dev->devnum;
1344 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301345 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001346
Michael Trimarchi956a4352008-12-10 15:52:06 +01001347 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001348 return -1;
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001349
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001350 perq = usb_stor_buf[0];
1351 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001352
1353 if ((perq & 0x1f) == 0x1f) {
1354 /* skip unknown devices */
1355 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001356 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001357 if ((modi&0x80) == 0x80) {
1358 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001359 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001360 }
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301361 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1362 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1363 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001364 dev_desc->vendor[8] = 0;
1365 dev_desc->product[16] = 0;
1366 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001367#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001368 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1369 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001370#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301371 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1372 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001373 if (usb_test_unit_ready(pccb, ss)) {
1374 printf("Device NOT ready\n"
1375 " Request Sense returned %02X %02X %02X\n",
1376 pccb->sense_buf[2], pccb->sense_buf[12],
1377 pccb->sense_buf[13]);
1378 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001379 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001380 return 1;
1381 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001382 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001383 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001384 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001385 memset(pccb->pdata, 0, 8);
1386 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001387 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001388 cap[0] = 2880;
1389 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001390 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001391 ss->flags &= ~USB_READY;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301392 debug("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001393#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001394 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1395 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001396#endif
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001397 cap[0] = cpu_to_be32(cap[0]);
1398 cap[1] = cpu_to_be32(cap[1]);
1399
wdenkde887eb2003-09-10 18:20:28 +00001400 /* this assumes bigendian! */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001401 cap[0] += 1;
1402 capacity = &cap[0];
1403 blksz = &cap[1];
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301404 debug("Capacity = 0x%lx, blocksz = 0x%lx\n", *capacity, *blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001405 dev_desc->lba = *capacity;
1406 dev_desc->blksz = *blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001407 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001408 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301409 debug(" address %d\n", dev_desc->target);
1410 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001411
1412 init_part(dev_desc);
1413
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301414 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001415 return 1;
1416}