blob: 05c96a8defe441d937900a6fae39fbb366a9e652 [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
Franck Jullien20f3eb82015-03-04 21:07:00 +0100211static int usb_storage_register(struct usb_device *dev, unsigned char iface)
212{
213 int lun, max_lun, start = usb_max_devs;
214 int nb_dev = 0;
215
216 if (!usb_storage_probe(dev, iface, &usb_stor[usb_max_devs]))
217 return nb_dev;
218
219 /*
220 * OK, it's a storage device. Iterate over its LUNs
221 * and populate `usb_dev_desc'.
222 */
223 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
224 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; lun++) {
225 usb_dev_desc[usb_max_devs].lun = lun;
226 if (usb_stor_get_info(dev, &usb_stor[start],
227 &usb_dev_desc[usb_max_devs]) == 1) {
228 nb_dev++;
229 }
230 }
231
232 return nb_dev;
233}
234
Michael Trimarchi956a4352008-12-10 15:52:06 +0100235/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200236 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000237 * to the user if mode = 1
238 * returns current device or -1 if no
239 */
240int usb_stor_scan(int mode)
241{
Franck Jullien20f3eb82015-03-04 21:07:00 +0100242 unsigned char i, iface;
wdenkaffae2b2002-08-17 09:36:01 +0000243 struct usb_device *dev;
244
Michael Trimarchi956a4352008-12-10 15:52:06 +0100245 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200246 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100247
wdenkaffae2b2002-08-17 09:36:01 +0000248 usb_disable_asynch(1); /* asynch transfer not allowed */
249
Michael Trimarchi956a4352008-12-10 15:52:06 +0100250 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
251 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100252 usb_dev_desc[i].if_type = IF_TYPE_USB;
253 usb_dev_desc[i].dev = i;
254 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200255 usb_dev_desc[i].target = 0xff;
256 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100257 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530258 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000259 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200260
Michael Trimarchi956a4352008-12-10 15:52:06 +0100261 usb_max_devs = 0;
262 for (i = 0; i < USB_MAX_DEVICE; i++) {
263 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530264 debug("i=%d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100265 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100266 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100267
Franck Jullien20f3eb82015-03-04 21:07:00 +0100268 for (iface = 0; iface < dev->config.no_of_if; iface++) {
269 usb_max_devs += usb_storage_register(dev, iface);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200270 }
Franck Jullien20f3eb82015-03-04 21:07:00 +0100271
Michael Trimarchi956a4352008-12-10 15:52:06 +0100272 /* if storage device */
273 if (usb_max_devs == USB_MAX_STOR_DEV) {
274 printf("max USB Storage Device reached: %d stopping\n",
275 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000276 break;
277 }
278 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200279
wdenkaffae2b2002-08-17 09:36:01 +0000280 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200281 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100282 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000283 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100284 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000285}
286
287static int usb_stor_irq(struct usb_device *dev)
288{
289 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100290 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000291
Michael Trimarchi956a4352008-12-10 15:52:06 +0100292 if (us->ip_wanted)
293 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000294 return 0;
295}
296
297
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530298#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000299
Michael Trimarchi956a4352008-12-10 15:52:06 +0100300static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000301{
302 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100303 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
304 for (i = 0; i < 12; i++)
305 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000306 printf("\n");
307}
308
309static void display_int_status(unsigned long tmp)
310{
311 printf("Status: %s %s %s %s %s %s %s\n",
312 (tmp & USB_ST_ACTIVE) ? "Active" : "",
313 (tmp & USB_ST_STALLED) ? "Stalled" : "",
314 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
315 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
316 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
317 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
318 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
319}
320#endif
321/***********************************************************************
322 * Data transfer routines
323 ***********************************************************************/
324
325static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
326{
327 int max_size;
328 int this_xfer;
329 int result;
330 int partial;
331 int maxtry;
332 int stat;
333
334 /* determine the maximum packet size for these transfers */
335 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
336
337 /* while we have data left to transfer */
338 while (length) {
339
340 /* calculate how long this will be -- maximum or a remainder */
341 this_xfer = length > max_size ? max_size : length;
342 length -= this_xfer;
343
344 /* setup the retry counter */
345 maxtry = 10;
346
347 /* set up the transfer loop */
348 do {
349 /* transfer the data */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530350 debug("Bulk xfer 0x%x(%d) try #%d\n",
351 (unsigned int)buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000352 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100353 this_xfer, &partial,
354 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530355 debug("bulk_msg returned %d xferred %d/%d\n",
356 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100357 if (us->pusb_dev->status != 0) {
358 /* if we stall, we need to clear it before
359 * we go on
360 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530361#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000362 display_int_status(us->pusb_dev->status);
363#endif
364 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530365 debug("stalled ->clearing endpoint" \
366 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000367 stat = us->pusb_dev->status;
368 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100369 us->pusb_dev->status = stat;
370 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530371 debug("bulk transferred" \
372 "with error %lX," \
373 " but data ok\n",
374 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000375 return 0;
376 }
377 else
378 return result;
379 }
380 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530381 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000382 return result;
383 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530384 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100385 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530386 debug(" %ld, but data ok\n",
387 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000388 return 0;
389 }
390 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530391 debug(" %ld, data %d\n",
392 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000393 if (!maxtry--)
394 return result;
395 }
396 /* update to show what data was transferred */
397 this_xfer -= partial;
398 buf += partial;
399 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100400 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000401 }
402
403 /* if we get here, we're done and successful */
404 return 0;
405}
406
wdenkde887eb2003-09-10 18:20:28 +0000407static int usb_stor_BBB_reset(struct us_data *us)
408{
409 int result;
410 unsigned int pipe;
411
412 /*
413 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
414 *
415 * For Reset Recovery the host shall issue in the following order:
416 * a) a Bulk-Only Mass Storage Reset
417 * b) a Clear Feature HALT to the Bulk-In endpoint
418 * c) a Clear Feature HALT to the Bulk-Out endpoint
419 *
420 * This is done in 3 steps.
421 *
422 * If the reset doesn't succeed, the device should be port reset.
423 *
424 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
425 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530426 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100427 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
428 US_BBB_RESET,
429 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000430 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200431
Michael Trimarchi956a4352008-12-10 15:52:06 +0100432 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530433 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000434 return -1;
435 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200436
wdenkde887eb2003-09-10 18:20:28 +0000437 /* long wait for reset */
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 reset\n",
440 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000441 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
442 result = usb_clear_halt(us->pusb_dev, pipe);
443 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000444 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530445 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
446 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000447 /* long wait for reset */
448 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
449 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000450 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530451 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
452 result, us->pusb_dev->status);
453 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000454 return 0;
455}
456
wdenkaffae2b2002-08-17 09:36:01 +0000457/* FIXME: this reset function doesn't really reset the port, and it
458 * should. Actually it should probably do what it's doing here, and
459 * reset the port physically
460 */
461static int usb_stor_CB_reset(struct us_data *us)
462{
463 unsigned char cmd[12];
464 int result;
465
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530466 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100467 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000468 cmd[0] = SCSI_SEND_DIAG;
469 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100470 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
471 US_CBI_ADSC,
472 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
473 0, us->ifnum, cmd, sizeof(cmd),
474 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000475
476 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000477 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530478 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
479 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000480 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
481 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
482
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530483 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000484 return 0;
485}
486
wdenkde887eb2003-09-10 18:20:28 +0000487/*
488 * Set up the command for a BBB device. Note that the actual SCSI
489 * command is copied into cbw.CBWCDB.
490 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000491static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000492{
493 int result;
494 int actlen;
495 int dir_in;
496 unsigned int pipe;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530497 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000498
499 dir_in = US_DIRECTION(srb->cmd[0]);
500
501#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530502 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100503 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
504 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000505 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100506 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000507 printf("cmd[%d] %#x ", result, srb->cmd[result]);
508 printf("\n");
509 }
510#endif
511 /* sanity checks */
512 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530513 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000514 return -1;
515 }
516
517 /* always OUT to the ep */
518 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
519
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530520 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
521 cbw->dCBWTag = cpu_to_le32(CBWTag++);
522 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
523 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
524 cbw->bCBWLUN = srb->lun;
525 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000526 /* copy the command data into the CBW command data buffer */
527 /* DST SRC LEN!!! */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530528 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
529 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100530 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000531 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530532 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000533 return result;
534}
535
wdenkaffae2b2002-08-17 09:36:01 +0000536/* FIXME: we also need a CBI_command which sets up the completion
537 * interrupt, and waits for it
538 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000539static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000540{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200541 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100542 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000543 unsigned int pipe;
544 unsigned long status;
545
Michael Trimarchi956a4352008-12-10 15:52:06 +0100546 retry = 5;
547 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000548
Michael Trimarchi956a4352008-12-10 15:52:06 +0100549 if (dir_in)
550 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
551 else
552 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
553
554 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530555 debug("CBI gets a command: Try %d\n", 5 - retry);
556#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000557 usb_show_srb(srb);
558#endif
559 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100560 result = usb_control_msg(us->pusb_dev,
561 usb_sndctrlpipe(us->pusb_dev , 0),
562 US_CBI_ADSC,
563 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000564 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100565 srb->cmd, srb->cmdlen,
566 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530567 debug("CB_transport: control msg returned %d, status %lX\n",
568 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000569 /* check the return code for the command */
570 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100571 if (us->pusb_dev->status & USB_ST_STALLED) {
572 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530573 debug(" stall during command found," \
574 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100575 usb_clear_halt(us->pusb_dev,
576 usb_sndctrlpipe(us->pusb_dev, 0));
577 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000578 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530579 debug(" error during command %02X" \
580 " Stat = %lX\n", srb->cmd[0],
581 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000582 return result;
583 }
584 /* transfer the data payload for this command, if one exists*/
585
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530586 debug("CB_transport: control msg returned %d," \
587 " direction is %s to go 0x%lx\n", result,
588 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000589 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 result = us_one_transfer(us, pipe, (char *)srb->pdata,
591 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530592 debug("CBI attempted to transfer data," \
593 " result is %d status %lX, len %d\n",
594 result, us->pusb_dev->status,
595 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100596 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000597 break;
598 } /* if (srb->datalen) */
599 else
600 break;
601 }
602 /* return result */
603
604 return result;
605}
606
607
Kim Phillipsb052b602012-10-29 13:34:32 +0000608static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000609{
610 int timeout;
611
wdenk5f495752004-02-26 23:46:20 +0000612 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100613 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000614 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
615 timeout = 1000;
616 while (timeout--) {
Kim Phillipsb052b602012-10-29 13:34:32 +0000617 if ((volatile int *) us->ip_wanted == NULL)
wdenkaffae2b2002-08-17 09:36:01 +0000618 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000619 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000620 }
621 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100622 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000623 us->ip_wanted = 0;
624 return USB_STOR_TRANSPORT_ERROR;
625 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530626 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
627 us->ip_data, us->pusb_dev->irq_act_len,
628 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000629 /* UFI gives us ASC and ASCQ, like a request sense */
630 if (us->subclass == US_SC_UFI) {
631 if (srb->cmd[0] == SCSI_REQ_SENSE ||
632 srb->cmd[0] == SCSI_INQUIRY)
633 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000634 else if (us->ip_data)
635 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000636 else
wdenk5f495752004-02-26 23:46:20 +0000637 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000638 }
639 /* otherwise, we interpret the data normally */
640 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000641 case 0x0001:
642 return USB_STOR_TRANSPORT_GOOD;
643 case 0x0002:
644 return USB_STOR_TRANSPORT_FAILED;
645 default:
646 return USB_STOR_TRANSPORT_ERROR;
647 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000648 return USB_STOR_TRANSPORT_ERROR;
649}
650
651#define USB_TRANSPORT_UNKNOWN_RETRY 5
652#define USB_TRANSPORT_NOT_READY_RETRY 10
653
wdenkde887eb2003-09-10 18:20:28 +0000654/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000655static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000656{
657 int result;
658
659 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100660 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000661 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000662 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000663 return result;
664}
665
Kim Phillipsb052b602012-10-29 13:34:32 +0000666static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000667{
668 int result, retry;
669 int dir_in;
670 int actlen, data_actlen;
671 unsigned int pipe, pipein, pipeout;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530672 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000673#ifdef BBB_XPORT_TRACE
674 unsigned char *ptr;
675 int index;
676#endif
677
678 dir_in = US_DIRECTION(srb->cmd[0]);
679
680 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530681 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000682 result = usb_stor_BBB_comdat(srb, us);
683 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530684 debug("failed to send CBW status %ld\n",
685 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000686 usb_stor_BBB_reset(us);
687 return USB_STOR_TRANSPORT_FAILED;
688 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200689 if (!(us->flags & USB_READY))
690 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000691 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
692 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
693 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000694 data_actlen = 0;
695 /* no data, go immediately to the STATUS phase */
696 if (srb->datalen == 0)
697 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530698 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000699 if (dir_in)
700 pipe = pipein;
701 else
702 pipe = pipeout;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100703 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
704 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000705 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100706 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530707 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000708 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100709 result = usb_stor_BBB_clear_endpt_stall(us,
710 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000711 if (result >= 0)
712 /* continue on to STATUS phase */
713 goto st;
714 }
715 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530716 debug("usb_bulk_msg error status %ld\n",
717 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000718 usb_stor_BBB_reset(us);
719 return USB_STOR_TRANSPORT_FAILED;
720 }
721#ifdef BBB_XPORT_TRACE
722 for (index = 0; index < data_actlen; index++)
723 printf("pdata[%d] %#x ", index, srb->pdata[index]);
724 printf("\n");
725#endif
726 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100727st:
wdenkde887eb2003-09-10 18:20:28 +0000728 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100729again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530730 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530731 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200732 &actlen, USB_CNTL_TIMEOUT*5);
733
wdenkde887eb2003-09-10 18:20:28 +0000734 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100735 if ((result < 0) && (retry < 1) &&
736 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530737 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000738 /* clear the STALL on the endpoint */
739 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
740 if (result >= 0 && (retry++ < 1))
741 /* do a retry */
742 goto again;
743 }
744 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530745 debug("usb_bulk_msg error status %ld\n",
746 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000747 usb_stor_BBB_reset(us);
748 return USB_STOR_TRANSPORT_FAILED;
749 }
750#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530751 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000752 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
753 printf("ptr[%d] %#x ", index, ptr[index]);
754 printf("\n");
755#endif
756 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530757 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000758 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
759 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530760 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530761 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000762 usb_stor_BBB_reset(us);
763 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530764 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530765 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000766 usb_stor_BBB_reset(us);
767 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530768 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530769 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000770 usb_stor_BBB_reset(us);
771 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530772 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530773 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000774 usb_stor_BBB_reset(us);
775 return USB_STOR_TRANSPORT_FAILED;
776 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530777 debug("transferred %dB instead of %ldB\n",
778 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000779 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530780 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530781 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000782 return USB_STOR_TRANSPORT_FAILED;
783 }
784
785 return result;
786}
787
Kim Phillipsb052b602012-10-29 13:34:32 +0000788static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000789{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100790 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000791 ccb *psrb;
792 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100793 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000794
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200795 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100796 status = USB_STOR_TRANSPORT_GOOD;
797 retry = 0;
798 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000799 /* issue the command */
800do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100801 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530802 debug("command / Data returned %d, status %lX\n",
803 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000804 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100805 if (us->protocol == US_PR_CBI) {
806 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000807 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100808 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530809 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000810 return status;
811 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100812 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
813 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
814 if (!us->ip_data) {
815 /* if the status is good, report it */
816 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530817 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000818 return status;
819 }
820 }
821 }
822 /* do we have to issue an auto request? */
823 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100824 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530825 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000826 us->transport_reset(us);
827 return USB_STOR_TRANSPORT_ERROR;
828 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100829 if ((us->protocol == US_PR_CBI) &&
830 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
831 (srb->cmd[0] == SCSI_INQUIRY))) {
832 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530833 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000834 return USB_STOR_TRANSPORT_GOOD;
835 }
836 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100837 memset(&psrb->cmd[0], 0, 12);
838 psrb->cmd[0] = SCSI_REQ_SENSE;
839 psrb->cmd[1] = srb->lun << 5;
840 psrb->cmd[4] = 18;
841 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200842 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100843 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530846 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 if (us->protocol == US_PR_CBI)
849 status = usb_stor_CBI_get_status(psrb, us);
850
851 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530852 debug(" AUTO REQUEST ERROR %ld\n",
853 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000854 return USB_STOR_TRANSPORT_ERROR;
855 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530856 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
857 srb->sense_buf[0], srb->sense_buf[2],
858 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000859 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100860 if ((srb->sense_buf[2] == 0) &&
861 (srb->sense_buf[12] == 0) &&
862 (srb->sense_buf[13] == 0)) {
863 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000864 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100865 }
866
wdenkaffae2b2002-08-17 09:36:01 +0000867 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100868 switch (srb->sense_buf[2]) {
869 case 0x01:
870 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000871 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000872 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100873 case 0x02:
874 /* Not Ready */
875 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
876 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
877 " 0x%02X (NOT READY)\n", srb->cmd[0],
878 srb->sense_buf[0], srb->sense_buf[2],
879 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000880 return USB_STOR_TRANSPORT_FAILED;
881 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000882 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000883 goto do_retry;
884 }
885 break;
886 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100887 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
888 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
889 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
890 srb->sense_buf[2], srb->sense_buf[12],
891 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000892 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100893 } else
wdenkde887eb2003-09-10 18:20:28 +0000894 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000895 break;
wdenkaffae2b2002-08-17 09:36:01 +0000896 }
897 return USB_STOR_TRANSPORT_FAILED;
898}
899
900
Michael Trimarchi956a4352008-12-10 15:52:06 +0100901static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000902{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903 int retry, i;
904 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000905 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906 memset(&srb->cmd[0], 0, 12);
907 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200908 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100909 srb->cmd[4] = 36;
910 srb->datalen = 36;
911 srb->cmdlen = 12;
912 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530913 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000915 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200916 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000917
Michael Trimarchi956a4352008-12-10 15:52:06 +0100918 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000919 printf("error in inquiry\n");
920 return -1;
921 }
922 return 0;
923}
924
Michael Trimarchi956a4352008-12-10 15:52:06 +0100925static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000926{
927 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000928
Michael Trimarchi956a4352008-12-10 15:52:06 +0100929 ptr = (char *)srb->pdata;
930 memset(&srb->cmd[0], 0, 12);
931 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200932 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100933 srb->cmd[4] = 18;
934 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200935 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100936 srb->cmdlen = 12;
937 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530938 debug("Request Sense returned %02X %02X %02X\n",
939 srb->sense_buf[2], srb->sense_buf[12],
940 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100941 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000942 return 0;
943}
944
Michael Trimarchi956a4352008-12-10 15:52:06 +0100945static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000946{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200947 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000948
wdenkaffae2b2002-08-17 09:36:01 +0000949 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100950 memset(&srb->cmd[0], 0, 12);
951 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200952 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100953 srb->datalen = 0;
954 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200955 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
956 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000957 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200958 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100959 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800960 /*
961 * Check the Key Code Qualifier, if it matches
962 * "Not Ready - medium not present"
963 * (the sense Key equals 0x2 and the ASC is 0x3a)
964 * return immediately as the medium being absent won't change
965 * unless there is a user action.
966 */
967 if ((srb->sense_buf[2] == 0x02) &&
968 (srb->sense_buf[12] == 0x3a))
969 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000970 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100971 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000972
wdenkaffae2b2002-08-17 09:36:01 +0000973 return -1;
974}
975
Michael Trimarchi956a4352008-12-10 15:52:06 +0100976static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000977{
978 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100979 /* XXX retries */
980 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000981 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100982 memset(&srb->cmd[0], 0, 12);
983 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200984 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100985 srb->datalen = 8;
986 srb->cmdlen = 12;
987 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000988 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100989 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000990
wdenkaffae2b2002-08-17 09:36:01 +0000991 return -1;
992}
993
Michael Trimarchi956a4352008-12-10 15:52:06 +0100994static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
995 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000996{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997 memset(&srb->cmd[0], 0, 12);
998 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200999 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001000 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1001 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1002 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1003 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1004 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1005 srb->cmd[8] = (unsigned char) blocks & 0xff;
1006 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301007 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001008 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001009}
1010
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301011static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1012 unsigned short blocks)
1013{
1014 memset(&srb->cmd[0], 0, 12);
1015 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001016 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301017 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1018 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1019 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1020 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1021 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1022 srb->cmd[8] = (unsigned char) blocks & 0xff;
1023 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301024 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301025 return ss->transport(srb, ss);
1026}
1027
wdenkaffae2b2002-08-17 09:36:01 +00001028
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001029#ifdef CONFIG_USB_BIN_FIXUP
1030/*
1031 * Some USB storage devices queried for SCSI identification data respond with
1032 * binary strings, which if output to the console freeze the terminal. The
1033 * workaround is to modify the vendor and product strings read from such
1034 * device with proper values (as reported by 'usb info').
1035 *
1036 * Vendor and product length limits are taken from the definition of
1037 * block_dev_desc_t in include/part.h.
1038 */
1039static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1040 unsigned char vendor[],
1041 unsigned char product[]) {
1042 const unsigned char max_vendor_len = 40;
1043 const unsigned char max_product_len = 20;
1044 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001045 strncpy((char *)vendor, "SMSC", max_vendor_len);
1046 strncpy((char *)product, "Flash Media Cntrller",
1047 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001048 }
1049}
1050#endif /* CONFIG_USB_BIN_FIXUP */
1051
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001052unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001053 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001054{
Gabe Black7d077682012-10-12 14:26:07 +00001055 lbaint_t start, blks;
1056 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001057 unsigned short smallblks;
1058 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001059 struct us_data *ss;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001060 int retry, i;
wdenk0e2874cb2004-03-02 14:05:39 +00001061 ccb *srb = &usb_ccb;
1062
1063 if (blkcnt == 0)
1064 return 0;
1065
1066 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001067 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301068 debug("\nusb_read: dev %d \n", device);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 dev = NULL;
1070 for (i = 0; i < USB_MAX_DEVICE; i++) {
1071 dev = usb_get_dev_index(i);
1072 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001073 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001074 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001075 break;
1076 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001077 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001078
1079 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 srb->lun = usb_dev_desc[device].lun;
1081 buf_addr = (unsigned long)buffer;
1082 start = blknr;
1083 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001084
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301085 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001086 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001087
wdenkaffae2b2002-08-17 09:36:01 +00001088 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001089 /* XXX need some comment here */
1090 retry = 2;
1091 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001092 if (blks > USB_MAX_XFER_BLK)
1093 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001094 else
1095 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001096retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001097 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001098 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001099 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1100 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001101 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301102 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001103 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001104 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001105 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001106 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001107 break;
1108 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001109 start += smallblks;
1110 blks -= smallblks;
1111 buf_addr += srb->datalen;
1112 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001113 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001114
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301115 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001116 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301117 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001118
wdenkaffae2b2002-08-17 09:36:01 +00001119 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001120 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001121 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001122 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001123}
1124
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001125unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001126 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301127{
Gabe Black7d077682012-10-12 14:26:07 +00001128 lbaint_t start, blks;
1129 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301130 unsigned short smallblks;
1131 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001132 struct us_data *ss;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301133 int retry, i;
1134 ccb *srb = &usb_ccb;
1135
1136 if (blkcnt == 0)
1137 return 0;
1138
1139 device &= 0xff;
1140 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301141 debug("\nusb_write: dev %d \n", device);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301142 dev = NULL;
1143 for (i = 0; i < USB_MAX_DEVICE; i++) {
1144 dev = usb_get_dev_index(i);
1145 if (dev == NULL)
1146 return 0;
1147 if (dev->devnum == usb_dev_desc[device].target)
1148 break;
1149 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001150 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301151
1152 usb_disable_asynch(1); /* asynch transfer not allowed */
1153
1154 srb->lun = usb_dev_desc[device].lun;
1155 buf_addr = (unsigned long)buffer;
1156 start = blknr;
1157 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301158
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301159 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001160 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301161
1162 do {
1163 /* If write fails retry for max retry count else
1164 * return with number of blocks written successfully.
1165 */
1166 retry = 2;
1167 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001168 if (blks > USB_MAX_XFER_BLK)
1169 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301170 else
1171 smallblks = (unsigned short) blks;
1172retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001173 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301174 usb_show_progress();
1175 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1176 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001177 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301178 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001179 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301180 if (retry--)
1181 goto retry_it;
1182 blkcnt -= blks;
1183 break;
1184 }
1185 start += smallblks;
1186 blks -= smallblks;
1187 buf_addr += srb->datalen;
1188 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001189 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301190
Simon Glassb43f7682014-10-15 04:38:38 -06001191 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1192 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301193
1194 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001195 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001196 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301197 return blkcnt;
1198
1199}
wdenkaffae2b2002-08-17 09:36:01 +00001200
1201/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001202int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1203 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001204{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001205 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001206 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301207 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001208 unsigned int flags = 0;
1209
1210 int protocol = 0;
1211 int subclass = 0;
1212
wdenkaffae2b2002-08-17 09:36:01 +00001213 /* let's examine the device now */
1214 iface = &dev->config.if_desc[ifnum];
1215
1216#if 0
1217 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301218 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001219 dev->descriptor.idProduct);
1220
1221 if ((dev->descriptor.idVendor) == 0x066b &&
1222 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301223 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001224 protocol = US_PR_CB;
1225 subclass = US_SC_UFI; /* an assumption */
1226 }
1227#endif
1228
1229 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001230 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1231 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1232 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001233 /* if it's not a mass storage, we go no further */
1234 return 0;
1235 }
1236
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001237 memset(ss, 0, sizeof(struct us_data));
1238
wdenkaffae2b2002-08-17 09:36:01 +00001239 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301240 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001241
1242 /* Initialize the us_data structure with some useful info */
1243 ss->flags = flags;
1244 ss->ifnum = ifnum;
1245 ss->pusb_dev = dev;
1246 ss->attention_done = 0;
1247
1248 /* If the device has subclass and protocol, then use that. Otherwise,
1249 * take data from the specific interface.
1250 */
1251 if (subclass) {
1252 ss->subclass = subclass;
1253 ss->protocol = protocol;
1254 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001255 ss->subclass = iface->desc.bInterfaceSubClass;
1256 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001257 }
1258
1259 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301260 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001261 switch (ss->protocol) {
1262 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301263 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001264 ss->transport = usb_stor_CB_transport;
1265 ss->transport_reset = usb_stor_CB_reset;
1266 break;
1267
1268 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301269 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001270 ss->transport = usb_stor_CB_transport;
1271 ss->transport_reset = usb_stor_CB_reset;
1272 break;
wdenkde887eb2003-09-10 18:20:28 +00001273 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301274 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001275 ss->transport = usb_stor_BBB_transport;
1276 ss->transport_reset = usb_stor_BBB_reset;
1277 break;
wdenkaffae2b2002-08-17 09:36:01 +00001278 default:
wdenk5f495752004-02-26 23:46:20 +00001279 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001280 return 0;
1281 break;
1282 }
1283
1284 /*
1285 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1286 * An optional interrupt is OK (necessary for CBI protocol).
1287 * We will ignore any others.
1288 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001289 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301290 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001291 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301292 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001293 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301294 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1295 ss->ep_in = ep_desc->bEndpointAddress &
1296 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001297 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001298 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301299 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001300 USB_ENDPOINT_NUMBER_MASK;
1301 }
1302
1303 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301304 if ((ep_desc->bmAttributes &
1305 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1306 ss->ep_int = ep_desc->bEndpointAddress &
1307 USB_ENDPOINT_NUMBER_MASK;
1308 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001309 }
1310 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301311 debug("Endpoints In %d Out %d Int %d\n",
1312 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001313
1314 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001315 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001316 !ss->ep_in || !ss->ep_out ||
1317 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301318 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001319 return 0;
1320 }
1321 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001322 /* We only handle certain protocols. Currently, these are
1323 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001324 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001325 */
wdenk5f495752004-02-26 23:46:20 +00001326 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1327 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001328 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001329 return 0;
1330 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001331 if (ss->ep_int) {
1332 /* we had found an interrupt endpoint, prepare irq pipe
1333 * set up the IRQ pipe and handler
1334 */
wdenkaffae2b2002-08-17 09:36:01 +00001335 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1336 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1337 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001338 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001339 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001340 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001341 return 1;
1342}
1343
Michael Trimarchi956a4352008-12-10 15:52:06 +01001344int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1345 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001346{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001347 unsigned char perq, modi;
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301348 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1349 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001350 unsigned long *capacity, *blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001351 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001352
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001353 pccb->pdata = usb_stor_buf;
1354
1355 dev_desc->target = dev->devnum;
1356 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301357 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001358
Michael Trimarchi956a4352008-12-10 15:52:06 +01001359 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001360 return -1;
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001361
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001362 perq = usb_stor_buf[0];
1363 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001364
Soeren Moche4828002014-11-08 07:02:14 +01001365 /*
1366 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1367 * they would not respond to test_unit_ready .
1368 */
1369 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001370 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001371 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001372 if ((modi&0x80) == 0x80) {
1373 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001374 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001375 }
Puneet Saxena6c9bb602012-04-03 14:56:06 +05301376 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1377 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1378 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001379 dev_desc->vendor[8] = 0;
1380 dev_desc->product[16] = 0;
1381 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001382#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001383 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1384 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001385#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301386 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1387 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001388 if (usb_test_unit_ready(pccb, ss)) {
1389 printf("Device NOT ready\n"
1390 " Request Sense returned %02X %02X %02X\n",
1391 pccb->sense_buf[2], pccb->sense_buf[12],
1392 pccb->sense_buf[13]);
1393 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001394 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001395 return 1;
1396 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001397 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001398 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001399 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001400 memset(pccb->pdata, 0, 8);
1401 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001402 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001403 cap[0] = 2880;
1404 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001405 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001406 ss->flags &= ~USB_READY;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301407 debug("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001408#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001409 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1410 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001411#endif
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001412 cap[0] = cpu_to_be32(cap[0]);
1413 cap[1] = cpu_to_be32(cap[1]);
1414
wdenkde887eb2003-09-10 18:20:28 +00001415 /* this assumes bigendian! */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001416 cap[0] += 1;
1417 capacity = &cap[0];
1418 blksz = &cap[1];
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301419 debug("Capacity = 0x%lx, blocksz = 0x%lx\n", *capacity, *blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001420 dev_desc->lba = *capacity;
1421 dev_desc->blksz = *blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001422 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001423 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301424 debug(" address %d\n", dev_desc->target);
1425 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001426
1427 init_part(dev_desc);
1428
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301429 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001430 return 1;
1431}