blob: a4ca7a59577ac5df307b40f99ca64ad793d17057 [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 */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300350 debug("Bulk xfer %p(%d) try #%d\n",
351 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!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300528
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530529 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
530 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100531 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000532 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530533 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000534 return result;
535}
536
wdenkaffae2b2002-08-17 09:36:01 +0000537/* FIXME: we also need a CBI_command which sets up the completion
538 * interrupt, and waits for it
539 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000540static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000541{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200542 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100543 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000544 unsigned int pipe;
545 unsigned long status;
546
Michael Trimarchi956a4352008-12-10 15:52:06 +0100547 retry = 5;
548 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000549
Michael Trimarchi956a4352008-12-10 15:52:06 +0100550 if (dir_in)
551 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
552 else
553 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
554
555 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530556 debug("CBI gets a command: Try %d\n", 5 - retry);
557#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000558 usb_show_srb(srb);
559#endif
560 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100561 result = usb_control_msg(us->pusb_dev,
562 usb_sndctrlpipe(us->pusb_dev , 0),
563 US_CBI_ADSC,
564 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000565 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100566 srb->cmd, srb->cmdlen,
567 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530568 debug("CB_transport: control msg returned %d, status %lX\n",
569 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000570 /* check the return code for the command */
571 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100572 if (us->pusb_dev->status & USB_ST_STALLED) {
573 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530574 debug(" stall during command found," \
575 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100576 usb_clear_halt(us->pusb_dev,
577 usb_sndctrlpipe(us->pusb_dev, 0));
578 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000579 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530580 debug(" error during command %02X" \
581 " Stat = %lX\n", srb->cmd[0],
582 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000583 return result;
584 }
585 /* transfer the data payload for this command, if one exists*/
586
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530587 debug("CB_transport: control msg returned %d," \
588 " direction is %s to go 0x%lx\n", result,
589 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000590 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100591 result = us_one_transfer(us, pipe, (char *)srb->pdata,
592 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530593 debug("CBI attempted to transfer data," \
594 " result is %d status %lX, len %d\n",
595 result, us->pusb_dev->status,
596 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100597 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000598 break;
599 } /* if (srb->datalen) */
600 else
601 break;
602 }
603 /* return result */
604
605 return result;
606}
607
608
Kim Phillipsb052b602012-10-29 13:34:32 +0000609static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000610{
611 int timeout;
612
wdenk5f495752004-02-26 23:46:20 +0000613 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100614 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000615 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
616 timeout = 1000;
617 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300618 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000619 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000620 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000621 }
622 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100623 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000624 us->ip_wanted = 0;
625 return USB_STOR_TRANSPORT_ERROR;
626 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530627 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
628 us->ip_data, us->pusb_dev->irq_act_len,
629 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000630 /* UFI gives us ASC and ASCQ, like a request sense */
631 if (us->subclass == US_SC_UFI) {
632 if (srb->cmd[0] == SCSI_REQ_SENSE ||
633 srb->cmd[0] == SCSI_INQUIRY)
634 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000635 else if (us->ip_data)
636 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000637 else
wdenk5f495752004-02-26 23:46:20 +0000638 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000639 }
640 /* otherwise, we interpret the data normally */
641 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000642 case 0x0001:
643 return USB_STOR_TRANSPORT_GOOD;
644 case 0x0002:
645 return USB_STOR_TRANSPORT_FAILED;
646 default:
647 return USB_STOR_TRANSPORT_ERROR;
648 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000649 return USB_STOR_TRANSPORT_ERROR;
650}
651
652#define USB_TRANSPORT_UNKNOWN_RETRY 5
653#define USB_TRANSPORT_NOT_READY_RETRY 10
654
wdenkde887eb2003-09-10 18:20:28 +0000655/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000656static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000657{
658 int result;
659
660 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100661 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000662 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000663 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000664 return result;
665}
666
Kim Phillipsb052b602012-10-29 13:34:32 +0000667static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000668{
669 int result, retry;
670 int dir_in;
671 int actlen, data_actlen;
672 unsigned int pipe, pipein, pipeout;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530673 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000674#ifdef BBB_XPORT_TRACE
675 unsigned char *ptr;
676 int index;
677#endif
678
679 dir_in = US_DIRECTION(srb->cmd[0]);
680
681 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530682 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000683 result = usb_stor_BBB_comdat(srb, us);
684 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530685 debug("failed to send CBW status %ld\n",
686 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000687 usb_stor_BBB_reset(us);
688 return USB_STOR_TRANSPORT_FAILED;
689 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200690 if (!(us->flags & USB_READY))
691 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000692 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
693 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
694 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000695 data_actlen = 0;
696 /* no data, go immediately to the STATUS phase */
697 if (srb->datalen == 0)
698 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530699 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000700 if (dir_in)
701 pipe = pipein;
702 else
703 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300704
Michael Trimarchi956a4352008-12-10 15:52:06 +0100705 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
706 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000707 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100708 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530709 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000710 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100711 result = usb_stor_BBB_clear_endpt_stall(us,
712 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000713 if (result >= 0)
714 /* continue on to STATUS phase */
715 goto st;
716 }
717 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530718 debug("usb_bulk_msg error status %ld\n",
719 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000720 usb_stor_BBB_reset(us);
721 return USB_STOR_TRANSPORT_FAILED;
722 }
723#ifdef BBB_XPORT_TRACE
724 for (index = 0; index < data_actlen; index++)
725 printf("pdata[%d] %#x ", index, srb->pdata[index]);
726 printf("\n");
727#endif
728 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100729st:
wdenkde887eb2003-09-10 18:20:28 +0000730 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100731again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530732 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530733 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200734 &actlen, USB_CNTL_TIMEOUT*5);
735
wdenkde887eb2003-09-10 18:20:28 +0000736 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100737 if ((result < 0) && (retry < 1) &&
738 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530739 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000740 /* clear the STALL on the endpoint */
741 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
742 if (result >= 0 && (retry++ < 1))
743 /* do a retry */
744 goto again;
745 }
746 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530747 debug("usb_bulk_msg error status %ld\n",
748 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000749 usb_stor_BBB_reset(us);
750 return USB_STOR_TRANSPORT_FAILED;
751 }
752#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530753 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000754 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
755 printf("ptr[%d] %#x ", index, ptr[index]);
756 printf("\n");
757#endif
758 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530759 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000760 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
761 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530762 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530763 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000764 usb_stor_BBB_reset(us);
765 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530766 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530767 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000768 usb_stor_BBB_reset(us);
769 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530770 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530771 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000772 usb_stor_BBB_reset(us);
773 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530774 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530775 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000776 usb_stor_BBB_reset(us);
777 return USB_STOR_TRANSPORT_FAILED;
778 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530779 debug("transferred %dB instead of %ldB\n",
780 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000781 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530782 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530783 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000784 return USB_STOR_TRANSPORT_FAILED;
785 }
786
787 return result;
788}
789
Kim Phillipsb052b602012-10-29 13:34:32 +0000790static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000791{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100792 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000793 ccb *psrb;
794 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100795 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000796
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200797 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100798 status = USB_STOR_TRANSPORT_GOOD;
799 retry = 0;
800 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000801 /* issue the command */
802do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100803 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530804 debug("command / Data returned %d, status %lX\n",
805 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000806 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100807 if (us->protocol == US_PR_CBI) {
808 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000809 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100810 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530811 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000812 return status;
813 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100814 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
815 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
816 if (!us->ip_data) {
817 /* if the status is good, report it */
818 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530819 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000820 return status;
821 }
822 }
823 }
824 /* do we have to issue an auto request? */
825 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100826 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530827 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000828 us->transport_reset(us);
829 return USB_STOR_TRANSPORT_ERROR;
830 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100831 if ((us->protocol == US_PR_CBI) &&
832 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
833 (srb->cmd[0] == SCSI_INQUIRY))) {
834 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530835 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000836 return USB_STOR_TRANSPORT_GOOD;
837 }
838 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100839 memset(&psrb->cmd[0], 0, 12);
840 psrb->cmd[0] = SCSI_REQ_SENSE;
841 psrb->cmd[1] = srb->lun << 5;
842 psrb->cmd[4] = 18;
843 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200844 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000846 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530848 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000849 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100850 if (us->protocol == US_PR_CBI)
851 status = usb_stor_CBI_get_status(psrb, us);
852
853 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530854 debug(" AUTO REQUEST ERROR %ld\n",
855 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000856 return USB_STOR_TRANSPORT_ERROR;
857 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530858 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
859 srb->sense_buf[0], srb->sense_buf[2],
860 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000861 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100862 if ((srb->sense_buf[2] == 0) &&
863 (srb->sense_buf[12] == 0) &&
864 (srb->sense_buf[13] == 0)) {
865 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000866 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100867 }
868
wdenkaffae2b2002-08-17 09:36:01 +0000869 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 switch (srb->sense_buf[2]) {
871 case 0x01:
872 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000873 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000874 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100875 case 0x02:
876 /* Not Ready */
877 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
878 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
879 " 0x%02X (NOT READY)\n", srb->cmd[0],
880 srb->sense_buf[0], srb->sense_buf[2],
881 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000882 return USB_STOR_TRANSPORT_FAILED;
883 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000884 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000885 goto do_retry;
886 }
887 break;
888 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100889 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
890 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
891 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
892 srb->sense_buf[2], srb->sense_buf[12],
893 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000894 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100895 } else
wdenkde887eb2003-09-10 18:20:28 +0000896 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000897 break;
wdenkaffae2b2002-08-17 09:36:01 +0000898 }
899 return USB_STOR_TRANSPORT_FAILED;
900}
901
902
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000904{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100905 int retry, i;
906 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000907 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100908 memset(&srb->cmd[0], 0, 12);
909 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200910 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 srb->cmd[4] = 36;
912 srb->datalen = 36;
913 srb->cmdlen = 12;
914 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530915 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100916 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000917 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200918 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000919
Michael Trimarchi956a4352008-12-10 15:52:06 +0100920 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000921 printf("error in inquiry\n");
922 return -1;
923 }
924 return 0;
925}
926
Michael Trimarchi956a4352008-12-10 15:52:06 +0100927static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000928{
929 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000930
Michael Trimarchi956a4352008-12-10 15:52:06 +0100931 ptr = (char *)srb->pdata;
932 memset(&srb->cmd[0], 0, 12);
933 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200934 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100935 srb->cmd[4] = 18;
936 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200937 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100938 srb->cmdlen = 12;
939 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530940 debug("Request Sense returned %02X %02X %02X\n",
941 srb->sense_buf[2], srb->sense_buf[12],
942 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100943 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000944 return 0;
945}
946
Michael Trimarchi956a4352008-12-10 15:52:06 +0100947static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000948{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200949 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000950
wdenkaffae2b2002-08-17 09:36:01 +0000951 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100952 memset(&srb->cmd[0], 0, 12);
953 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200954 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100955 srb->datalen = 0;
956 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200957 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
958 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000959 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200960 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100961 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800962 /*
963 * Check the Key Code Qualifier, if it matches
964 * "Not Ready - medium not present"
965 * (the sense Key equals 0x2 and the ASC is 0x3a)
966 * return immediately as the medium being absent won't change
967 * unless there is a user action.
968 */
969 if ((srb->sense_buf[2] == 0x02) &&
970 (srb->sense_buf[12] == 0x3a))
971 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000972 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100973 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000974
wdenkaffae2b2002-08-17 09:36:01 +0000975 return -1;
976}
977
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000979{
980 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 /* XXX retries */
982 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000983 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100984 memset(&srb->cmd[0], 0, 12);
985 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200986 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100987 srb->datalen = 8;
988 srb->cmdlen = 12;
989 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000990 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100991 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000992
wdenkaffae2b2002-08-17 09:36:01 +0000993 return -1;
994}
995
Michael Trimarchi956a4352008-12-10 15:52:06 +0100996static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
997 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000998{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100999 memset(&srb->cmd[0], 0, 12);
1000 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001001 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001002 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1003 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1004 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1005 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1006 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1007 srb->cmd[8] = (unsigned char) blocks & 0xff;
1008 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301009 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001010 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001011}
1012
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301013static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1014 unsigned short blocks)
1015{
1016 memset(&srb->cmd[0], 0, 12);
1017 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001018 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301019 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1020 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1021 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1022 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1023 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1024 srb->cmd[8] = (unsigned char) blocks & 0xff;
1025 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301026 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301027 return ss->transport(srb, ss);
1028}
1029
wdenkaffae2b2002-08-17 09:36:01 +00001030
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001031#ifdef CONFIG_USB_BIN_FIXUP
1032/*
1033 * Some USB storage devices queried for SCSI identification data respond with
1034 * binary strings, which if output to the console freeze the terminal. The
1035 * workaround is to modify the vendor and product strings read from such
1036 * device with proper values (as reported by 'usb info').
1037 *
1038 * Vendor and product length limits are taken from the definition of
1039 * block_dev_desc_t in include/part.h.
1040 */
1041static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1042 unsigned char vendor[],
1043 unsigned char product[]) {
1044 const unsigned char max_vendor_len = 40;
1045 const unsigned char max_product_len = 20;
1046 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001047 strncpy((char *)vendor, "SMSC", max_vendor_len);
1048 strncpy((char *)product, "Flash Media Cntrller",
1049 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001050 }
1051}
1052#endif /* CONFIG_USB_BIN_FIXUP */
1053
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001054unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001055 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001056{
Gabe Black7d077682012-10-12 14:26:07 +00001057 lbaint_t start, blks;
1058 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001059 unsigned short smallblks;
1060 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001061 struct us_data *ss;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001062 int retry, i;
wdenk0e2874cb2004-03-02 14:05:39 +00001063 ccb *srb = &usb_ccb;
1064
1065 if (blkcnt == 0)
1066 return 0;
1067
1068 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001069 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301070 debug("\nusb_read: dev %d \n", device);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001071 dev = NULL;
1072 for (i = 0; i < USB_MAX_DEVICE; i++) {
1073 dev = usb_get_dev_index(i);
1074 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001075 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001076 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001077 break;
1078 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001079 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001080
1081 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001082 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001083 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001084 start = blknr;
1085 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001086
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301087 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001088 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001089
wdenkaffae2b2002-08-17 09:36:01 +00001090 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001091 /* XXX need some comment here */
1092 retry = 2;
1093 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001094 if (blks > USB_MAX_XFER_BLK)
1095 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001096 else
1097 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001098retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001099 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001100 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001101 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1102 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001103 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301104 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001105 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001106 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001107 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001108 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001109 break;
1110 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001111 start += smallblks;
1112 blks -= smallblks;
1113 buf_addr += srb->datalen;
1114 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001115 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001116
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301117 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001118 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301119 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001120
wdenkaffae2b2002-08-17 09:36:01 +00001121 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001122 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001123 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001124 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001125}
1126
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001127unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001128 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301129{
Gabe Black7d077682012-10-12 14:26:07 +00001130 lbaint_t start, blks;
1131 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301132 unsigned short smallblks;
1133 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001134 struct us_data *ss;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301135 int retry, i;
1136 ccb *srb = &usb_ccb;
1137
1138 if (blkcnt == 0)
1139 return 0;
1140
1141 device &= 0xff;
1142 /* Setup device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301143 debug("\nusb_write: dev %d \n", device);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301144 dev = NULL;
1145 for (i = 0; i < USB_MAX_DEVICE; i++) {
1146 dev = usb_get_dev_index(i);
1147 if (dev == NULL)
1148 return 0;
1149 if (dev->devnum == usb_dev_desc[device].target)
1150 break;
1151 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001152 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301153
1154 usb_disable_asynch(1); /* asynch transfer not allowed */
1155
1156 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001157 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301158 start = blknr;
1159 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301160
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301161 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001162 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301163
1164 do {
1165 /* If write fails retry for max retry count else
1166 * return with number of blocks written successfully.
1167 */
1168 retry = 2;
1169 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001170 if (blks > USB_MAX_XFER_BLK)
1171 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301172 else
1173 smallblks = (unsigned short) blks;
1174retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001175 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301176 usb_show_progress();
1177 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1178 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001179 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301180 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001181 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301182 if (retry--)
1183 goto retry_it;
1184 blkcnt -= blks;
1185 break;
1186 }
1187 start += smallblks;
1188 blks -= smallblks;
1189 buf_addr += srb->datalen;
1190 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001191 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301192
Simon Glassb43f7682014-10-15 04:38:38 -06001193 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1194 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301195
1196 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001197 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001198 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301199 return blkcnt;
1200
1201}
wdenkaffae2b2002-08-17 09:36:01 +00001202
1203/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001204int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1205 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001206{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001207 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001208 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301209 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001210 unsigned int flags = 0;
1211
1212 int protocol = 0;
1213 int subclass = 0;
1214
wdenkaffae2b2002-08-17 09:36:01 +00001215 /* let's examine the device now */
1216 iface = &dev->config.if_desc[ifnum];
1217
1218#if 0
1219 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301220 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001221 dev->descriptor.idProduct);
1222
1223 if ((dev->descriptor.idVendor) == 0x066b &&
1224 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301225 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001226 protocol = US_PR_CB;
1227 subclass = US_SC_UFI; /* an assumption */
1228 }
1229#endif
1230
1231 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001232 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1233 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1234 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001235 /* if it's not a mass storage, we go no further */
1236 return 0;
1237 }
1238
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001239 memset(ss, 0, sizeof(struct us_data));
1240
wdenkaffae2b2002-08-17 09:36:01 +00001241 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301242 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001243
1244 /* Initialize the us_data structure with some useful info */
1245 ss->flags = flags;
1246 ss->ifnum = ifnum;
1247 ss->pusb_dev = dev;
1248 ss->attention_done = 0;
1249
1250 /* If the device has subclass and protocol, then use that. Otherwise,
1251 * take data from the specific interface.
1252 */
1253 if (subclass) {
1254 ss->subclass = subclass;
1255 ss->protocol = protocol;
1256 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001257 ss->subclass = iface->desc.bInterfaceSubClass;
1258 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001259 }
1260
1261 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301262 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001263 switch (ss->protocol) {
1264 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301265 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001266 ss->transport = usb_stor_CB_transport;
1267 ss->transport_reset = usb_stor_CB_reset;
1268 break;
1269
1270 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301271 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001272 ss->transport = usb_stor_CB_transport;
1273 ss->transport_reset = usb_stor_CB_reset;
1274 break;
wdenkde887eb2003-09-10 18:20:28 +00001275 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301276 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001277 ss->transport = usb_stor_BBB_transport;
1278 ss->transport_reset = usb_stor_BBB_reset;
1279 break;
wdenkaffae2b2002-08-17 09:36:01 +00001280 default:
wdenk5f495752004-02-26 23:46:20 +00001281 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001282 return 0;
1283 break;
1284 }
1285
1286 /*
1287 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1288 * An optional interrupt is OK (necessary for CBI protocol).
1289 * We will ignore any others.
1290 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001291 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301292 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001293 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301294 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001295 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301296 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1297 ss->ep_in = ep_desc->bEndpointAddress &
1298 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001299 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001300 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301301 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001302 USB_ENDPOINT_NUMBER_MASK;
1303 }
1304
1305 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301306 if ((ep_desc->bmAttributes &
1307 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1308 ss->ep_int = ep_desc->bEndpointAddress &
1309 USB_ENDPOINT_NUMBER_MASK;
1310 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001311 }
1312 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301313 debug("Endpoints In %d Out %d Int %d\n",
1314 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001315
1316 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001317 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001318 !ss->ep_in || !ss->ep_out ||
1319 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301320 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001321 return 0;
1322 }
1323 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001324 /* We only handle certain protocols. Currently, these are
1325 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001326 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001327 */
wdenk5f495752004-02-26 23:46:20 +00001328 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1329 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001330 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001331 return 0;
1332 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001333 if (ss->ep_int) {
1334 /* we had found an interrupt endpoint, prepare irq pipe
1335 * set up the IRQ pipe and handler
1336 */
wdenkaffae2b2002-08-17 09:36:01 +00001337 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1338 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1339 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001340 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001341 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001342 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001343 return 1;
1344}
1345
Michael Trimarchi956a4352008-12-10 15:52:06 +01001346int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1347 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001348{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001349 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001350 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1351 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1352 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001353 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001354
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001355 pccb->pdata = usb_stor_buf;
1356
1357 dev_desc->target = dev->devnum;
1358 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301359 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001360
Michael Trimarchi956a4352008-12-10 15:52:06 +01001361 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001362 return -1;
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001363
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001364 perq = usb_stor_buf[0];
1365 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001366
Soeren Moche4828002014-11-08 07:02:14 +01001367 /*
1368 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1369 * they would not respond to test_unit_ready .
1370 */
1371 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001372 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001373 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001374 if ((modi&0x80) == 0x80) {
1375 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001376 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001377 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001378 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1379 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1380 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001381 dev_desc->vendor[8] = 0;
1382 dev_desc->product[16] = 0;
1383 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001384#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001385 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1386 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001387#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301388 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1389 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001390 if (usb_test_unit_ready(pccb, ss)) {
1391 printf("Device NOT ready\n"
1392 " Request Sense returned %02X %02X %02X\n",
1393 pccb->sense_buf[2], pccb->sense_buf[12],
1394 pccb->sense_buf[13]);
1395 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001396 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001397 return 1;
1398 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001399 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001400 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001401 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001402 memset(pccb->pdata, 0, 8);
1403 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001404 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001405 cap[0] = 2880;
1406 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001407 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001408 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001409 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001410#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001411 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1412 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001413
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001414 cap[0] = cpu_to_be32(cap[0]);
1415 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001416#endif
1417
1418 capacity = be32_to_cpu(cap[0]) + 1;
1419 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001420
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001421 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1422 dev_desc->lba = capacity;
1423 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001424 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001425 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301426 debug(" address %d\n", dev_desc->target);
1427 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001428
1429 init_part(dev_desc);
1430
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301431 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001432 return 1;
1433}