blob: 2955b325b8f05076766853c9cacc3f2745424b63 [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)));
Michael Trimarchi956a4352008-12-10 15:52:06 +010059static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000060
wdenkaffae2b2002-08-17 09:36:01 +000061#define USB_MAX_STOR_DEV 5
Michael Trimarchi956a4352008-12-10 15:52:06 +010062static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000063
64static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
65
66struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +010067typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
68typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000069
70struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010071 struct usb_device *pusb_dev; /* this usb_device */
72
73 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020074# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010075 unsigned char ifnum; /* interface number */
76 unsigned char ep_in; /* in endpoint */
77 unsigned char ep_out; /* out ....... */
78 unsigned char ep_int; /* interrupt . */
79 unsigned char subclass; /* as in overview */
80 unsigned char protocol; /* .............. */
81 unsigned char attention_done; /* force attn on first cmd */
82 unsigned short ip_data; /* interrupt data */
83 int action; /* what to do */
84 int ip_wanted; /* needed */
85 int *irq_handle; /* for USB int requests */
86 unsigned int irqpipe; /* pipe for release_irq */
87 unsigned char irqmaxp; /* max packed for irq Pipe */
88 unsigned char irqinterval; /* Intervall for IRQ Pipe */
89 ccb *srb; /* current srb */
90 trans_reset transport_reset; /* reset routine */
91 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000092};
93
Benoît Thébaudeau938051f2012-08-10 18:26:50 +020094#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +000095/*
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +020096 * The U-Boot EHCI driver can handle any transfer length as long as there is
97 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
98 * limited to 65535 blocks.
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +000099 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200100#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200101#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200102#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200103#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000104
wdenkaffae2b2002-08-17 09:36:01 +0000105static struct us_data usb_stor[USB_MAX_STOR_DEV];
106
107
wdenk5f495752004-02-26 23:46:20 +0000108#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000109#define USB_STOR_TRANSPORT_FAILED -1
110#define USB_STOR_TRANSPORT_ERROR -2
111
Michael Trimarchi956a4352008-12-10 15:52:06 +0100112int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
113 block_dev_desc_t *dev_desc);
114int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
115 struct us_data *ss);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200116unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000117 lbaint_t blkcnt, void *buffer);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200118unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000119 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000120struct usb_device * usb_get_dev_index(int index);
121void uhci_show_temp_int_td(void);
122
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000123#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000124block_dev_desc_t *usb_stor_get_dev(int index)
125{
Kim B. Heino300ea512010-03-12 15:46:56 +0200126 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000127}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000128#endif
wdenkaffae2b2002-08-17 09:36:01 +0000129
Kim Phillipsb052b602012-10-29 13:34:32 +0000130static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000131{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200132 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000133}
134
Michael Trimarchi956a4352008-12-10 15:52:06 +0100135/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200136 * show info on storage devices; 'usb start/init' must be invoked earlier
137 * as we only retrieve structures populated during devices initialization
138 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100139int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200140{
141 int i;
142
Aras Vaichas7ede1862008-03-25 12:09:07 +1100143 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200144 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100145 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200146 dev_print(&usb_dev_desc[i]);
147 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100148 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100149 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700150
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100151 printf("No storage devices, perhaps not 'usb start'ed..?\n");
152 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200153}
154
Ludovic Courtès134396c2010-10-05 22:04:26 +0200155static unsigned int usb_get_max_lun(struct us_data *us)
156{
157 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530158 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200159 len = usb_control_msg(us->pusb_dev,
160 usb_rcvctrlpipe(us->pusb_dev, 0),
161 US_BBB_GET_MAX_LUN,
162 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
163 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530164 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200165 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530166 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530167 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200168}
169
Franck Jullien20f3eb82015-03-04 21:07:00 +0100170static int usb_storage_register(struct usb_device *dev, unsigned char iface)
171{
172 int lun, max_lun, start = usb_max_devs;
173 int nb_dev = 0;
174
175 if (!usb_storage_probe(dev, iface, &usb_stor[usb_max_devs]))
176 return nb_dev;
177
178 /*
179 * OK, it's a storage device. Iterate over its LUNs
180 * and populate `usb_dev_desc'.
181 */
182 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
183 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; lun++) {
184 usb_dev_desc[usb_max_devs].lun = lun;
185 if (usb_stor_get_info(dev, &usb_stor[start],
186 &usb_dev_desc[usb_max_devs]) == 1) {
187 nb_dev++;
188 }
189 }
190
191 return nb_dev;
192}
193
Michael Trimarchi956a4352008-12-10 15:52:06 +0100194/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200195 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000196 * to the user if mode = 1
197 * returns current device or -1 if no
198 */
199int usb_stor_scan(int mode)
200{
Franck Jullien20f3eb82015-03-04 21:07:00 +0100201 unsigned char i, iface;
wdenkaffae2b2002-08-17 09:36:01 +0000202 struct usb_device *dev;
203
Michael Trimarchi956a4352008-12-10 15:52:06 +0100204 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200205 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100206
wdenkaffae2b2002-08-17 09:36:01 +0000207 usb_disable_asynch(1); /* asynch transfer not allowed */
208
Michael Trimarchi956a4352008-12-10 15:52:06 +0100209 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
210 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100211 usb_dev_desc[i].if_type = IF_TYPE_USB;
212 usb_dev_desc[i].dev = i;
213 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200214 usb_dev_desc[i].target = 0xff;
215 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100216 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530217 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000218 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200219
Michael Trimarchi956a4352008-12-10 15:52:06 +0100220 usb_max_devs = 0;
221 for (i = 0; i < USB_MAX_DEVICE; i++) {
222 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530223 debug("i=%d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100224 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100225 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100226
Franck Jullien20f3eb82015-03-04 21:07:00 +0100227 for (iface = 0; iface < dev->config.no_of_if; iface++) {
228 usb_max_devs += usb_storage_register(dev, iface);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200229 }
Franck Jullien20f3eb82015-03-04 21:07:00 +0100230
Michael Trimarchi956a4352008-12-10 15:52:06 +0100231 /* if storage device */
232 if (usb_max_devs == USB_MAX_STOR_DEV) {
233 printf("max USB Storage Device reached: %d stopping\n",
234 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000235 break;
236 }
237 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200238
wdenkaffae2b2002-08-17 09:36:01 +0000239 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200240 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100241 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000242 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100243 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000244}
245
246static int usb_stor_irq(struct usb_device *dev)
247{
248 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100249 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000250
Michael Trimarchi956a4352008-12-10 15:52:06 +0100251 if (us->ip_wanted)
252 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000253 return 0;
254}
255
256
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530257#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000258
Michael Trimarchi956a4352008-12-10 15:52:06 +0100259static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000260{
261 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100262 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
263 for (i = 0; i < 12; i++)
264 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000265 printf("\n");
266}
267
268static void display_int_status(unsigned long tmp)
269{
270 printf("Status: %s %s %s %s %s %s %s\n",
271 (tmp & USB_ST_ACTIVE) ? "Active" : "",
272 (tmp & USB_ST_STALLED) ? "Stalled" : "",
273 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
274 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
275 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
276 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
277 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
278}
279#endif
280/***********************************************************************
281 * Data transfer routines
282 ***********************************************************************/
283
284static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
285{
286 int max_size;
287 int this_xfer;
288 int result;
289 int partial;
290 int maxtry;
291 int stat;
292
293 /* determine the maximum packet size for these transfers */
294 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
295
296 /* while we have data left to transfer */
297 while (length) {
298
299 /* calculate how long this will be -- maximum or a remainder */
300 this_xfer = length > max_size ? max_size : length;
301 length -= this_xfer;
302
303 /* setup the retry counter */
304 maxtry = 10;
305
306 /* set up the transfer loop */
307 do {
308 /* transfer the data */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300309 debug("Bulk xfer %p(%d) try #%d\n",
310 buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000311 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100312 this_xfer, &partial,
313 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530314 debug("bulk_msg returned %d xferred %d/%d\n",
315 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100316 if (us->pusb_dev->status != 0) {
317 /* if we stall, we need to clear it before
318 * we go on
319 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530320#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000321 display_int_status(us->pusb_dev->status);
322#endif
323 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530324 debug("stalled ->clearing endpoint" \
325 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000326 stat = us->pusb_dev->status;
327 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100328 us->pusb_dev->status = stat;
329 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530330 debug("bulk transferred" \
331 "with error %lX," \
332 " but data ok\n",
333 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
335 }
336 else
337 return result;
338 }
339 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530340 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000341 return result;
342 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530343 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100344 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530345 debug(" %ld, but data ok\n",
346 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000347 return 0;
348 }
349 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530350 debug(" %ld, data %d\n",
351 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000352 if (!maxtry--)
353 return result;
354 }
355 /* update to show what data was transferred */
356 this_xfer -= partial;
357 buf += partial;
358 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100359 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000360 }
361
362 /* if we get here, we're done and successful */
363 return 0;
364}
365
wdenkde887eb2003-09-10 18:20:28 +0000366static int usb_stor_BBB_reset(struct us_data *us)
367{
368 int result;
369 unsigned int pipe;
370
371 /*
372 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
373 *
374 * For Reset Recovery the host shall issue in the following order:
375 * a) a Bulk-Only Mass Storage Reset
376 * b) a Clear Feature HALT to the Bulk-In endpoint
377 * c) a Clear Feature HALT to the Bulk-Out endpoint
378 *
379 * This is done in 3 steps.
380 *
381 * If the reset doesn't succeed, the device should be port reset.
382 *
383 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
384 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530385 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100386 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
387 US_BBB_RESET,
388 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000389 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200390
Michael Trimarchi956a4352008-12-10 15:52:06 +0100391 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530392 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000393 return -1;
394 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200395
wdenkde887eb2003-09-10 18:20:28 +0000396 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000397 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530398 debug("BBB_reset result %d: status %lX reset\n",
399 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000400 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
401 result = usb_clear_halt(us->pusb_dev, pipe);
402 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000403 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530404 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
405 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000406 /* long wait for reset */
407 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
408 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000409 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530410 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
411 result, us->pusb_dev->status);
412 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000413 return 0;
414}
415
wdenkaffae2b2002-08-17 09:36:01 +0000416/* FIXME: this reset function doesn't really reset the port, and it
417 * should. Actually it should probably do what it's doing here, and
418 * reset the port physically
419 */
420static int usb_stor_CB_reset(struct us_data *us)
421{
422 unsigned char cmd[12];
423 int result;
424
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530425 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100426 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000427 cmd[0] = SCSI_SEND_DIAG;
428 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100429 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
430 US_CBI_ADSC,
431 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
432 0, us->ifnum, cmd, sizeof(cmd),
433 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000434
435 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000436 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530437 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
438 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000439 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
440 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
441
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530442 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000443 return 0;
444}
445
wdenkde887eb2003-09-10 18:20:28 +0000446/*
447 * Set up the command for a BBB device. Note that the actual SCSI
448 * command is copied into cbw.CBWCDB.
449 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000450static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000451{
452 int result;
453 int actlen;
454 int dir_in;
455 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600456 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000457
458 dir_in = US_DIRECTION(srb->cmd[0]);
459
460#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530461 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100462 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
463 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000464 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100465 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000466 printf("cmd[%d] %#x ", result, srb->cmd[result]);
467 printf("\n");
468 }
469#endif
470 /* sanity checks */
471 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530472 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000473 return -1;
474 }
475
476 /* always OUT to the ep */
477 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
478
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530479 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
480 cbw->dCBWTag = cpu_to_le32(CBWTag++);
481 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
482 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
483 cbw->bCBWLUN = srb->lun;
484 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000485 /* copy the command data into the CBW command data buffer */
486 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300487
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530488 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
489 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100490 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000491 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530492 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000493 return result;
494}
495
wdenkaffae2b2002-08-17 09:36:01 +0000496/* FIXME: we also need a CBI_command which sets up the completion
497 * interrupt, and waits for it
498 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000499static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000500{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200501 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100502 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000503 unsigned int pipe;
504 unsigned long status;
505
Michael Trimarchi956a4352008-12-10 15:52:06 +0100506 retry = 5;
507 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000508
Michael Trimarchi956a4352008-12-10 15:52:06 +0100509 if (dir_in)
510 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
511 else
512 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
513
514 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530515 debug("CBI gets a command: Try %d\n", 5 - retry);
516#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000517 usb_show_srb(srb);
518#endif
519 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100520 result = usb_control_msg(us->pusb_dev,
521 usb_sndctrlpipe(us->pusb_dev , 0),
522 US_CBI_ADSC,
523 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000524 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100525 srb->cmd, srb->cmdlen,
526 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530527 debug("CB_transport: control msg returned %d, status %lX\n",
528 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000529 /* check the return code for the command */
530 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100531 if (us->pusb_dev->status & USB_ST_STALLED) {
532 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530533 debug(" stall during command found," \
534 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100535 usb_clear_halt(us->pusb_dev,
536 usb_sndctrlpipe(us->pusb_dev, 0));
537 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000538 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530539 debug(" error during command %02X" \
540 " Stat = %lX\n", srb->cmd[0],
541 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000542 return result;
543 }
544 /* transfer the data payload for this command, if one exists*/
545
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530546 debug("CB_transport: control msg returned %d," \
547 " direction is %s to go 0x%lx\n", result,
548 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000549 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100550 result = us_one_transfer(us, pipe, (char *)srb->pdata,
551 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530552 debug("CBI attempted to transfer data," \
553 " result is %d status %lX, len %d\n",
554 result, us->pusb_dev->status,
555 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100556 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000557 break;
558 } /* if (srb->datalen) */
559 else
560 break;
561 }
562 /* return result */
563
564 return result;
565}
566
567
Kim Phillipsb052b602012-10-29 13:34:32 +0000568static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000569{
570 int timeout;
571
wdenk5f495752004-02-26 23:46:20 +0000572 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100573 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000574 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
575 timeout = 1000;
576 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300577 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000578 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000579 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000580 }
581 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100582 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000583 us->ip_wanted = 0;
584 return USB_STOR_TRANSPORT_ERROR;
585 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530586 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
587 us->ip_data, us->pusb_dev->irq_act_len,
588 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000589 /* UFI gives us ASC and ASCQ, like a request sense */
590 if (us->subclass == US_SC_UFI) {
591 if (srb->cmd[0] == SCSI_REQ_SENSE ||
592 srb->cmd[0] == SCSI_INQUIRY)
593 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000594 else if (us->ip_data)
595 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000596 else
wdenk5f495752004-02-26 23:46:20 +0000597 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000598 }
599 /* otherwise, we interpret the data normally */
600 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000601 case 0x0001:
602 return USB_STOR_TRANSPORT_GOOD;
603 case 0x0002:
604 return USB_STOR_TRANSPORT_FAILED;
605 default:
606 return USB_STOR_TRANSPORT_ERROR;
607 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000608 return USB_STOR_TRANSPORT_ERROR;
609}
610
611#define USB_TRANSPORT_UNKNOWN_RETRY 5
612#define USB_TRANSPORT_NOT_READY_RETRY 10
613
wdenkde887eb2003-09-10 18:20:28 +0000614/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000615static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000616{
617 int result;
618
619 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100620 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000621 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000622 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000623 return result;
624}
625
Kim Phillipsb052b602012-10-29 13:34:32 +0000626static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000627{
628 int result, retry;
629 int dir_in;
630 int actlen, data_actlen;
631 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600632 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000633#ifdef BBB_XPORT_TRACE
634 unsigned char *ptr;
635 int index;
636#endif
637
638 dir_in = US_DIRECTION(srb->cmd[0]);
639
640 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530641 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000642 result = usb_stor_BBB_comdat(srb, us);
643 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530644 debug("failed to send CBW status %ld\n",
645 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000646 usb_stor_BBB_reset(us);
647 return USB_STOR_TRANSPORT_FAILED;
648 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200649 if (!(us->flags & USB_READY))
650 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000651 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
652 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
653 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000654 data_actlen = 0;
655 /* no data, go immediately to the STATUS phase */
656 if (srb->datalen == 0)
657 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530658 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000659 if (dir_in)
660 pipe = pipein;
661 else
662 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300663
Michael Trimarchi956a4352008-12-10 15:52:06 +0100664 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
665 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000666 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100667 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530668 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000669 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100670 result = usb_stor_BBB_clear_endpt_stall(us,
671 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000672 if (result >= 0)
673 /* continue on to STATUS phase */
674 goto st;
675 }
676 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530677 debug("usb_bulk_msg error status %ld\n",
678 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000679 usb_stor_BBB_reset(us);
680 return USB_STOR_TRANSPORT_FAILED;
681 }
682#ifdef BBB_XPORT_TRACE
683 for (index = 0; index < data_actlen; index++)
684 printf("pdata[%d] %#x ", index, srb->pdata[index]);
685 printf("\n");
686#endif
687 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100688st:
wdenkde887eb2003-09-10 18:20:28 +0000689 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100690again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530691 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530692 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200693 &actlen, USB_CNTL_TIMEOUT*5);
694
wdenkde887eb2003-09-10 18:20:28 +0000695 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100696 if ((result < 0) && (retry < 1) &&
697 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530698 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000699 /* clear the STALL on the endpoint */
700 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
701 if (result >= 0 && (retry++ < 1))
702 /* do a retry */
703 goto again;
704 }
705 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530706 debug("usb_bulk_msg error status %ld\n",
707 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000708 usb_stor_BBB_reset(us);
709 return USB_STOR_TRANSPORT_FAILED;
710 }
711#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530712 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000713 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
714 printf("ptr[%d] %#x ", index, ptr[index]);
715 printf("\n");
716#endif
717 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530718 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000719 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
720 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530721 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530722 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000723 usb_stor_BBB_reset(us);
724 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530725 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530726 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000727 usb_stor_BBB_reset(us);
728 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530729 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530730 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000731 usb_stor_BBB_reset(us);
732 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530733 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530734 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000735 usb_stor_BBB_reset(us);
736 return USB_STOR_TRANSPORT_FAILED;
737 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530738 debug("transferred %dB instead of %ldB\n",
739 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000740 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530741 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530742 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000743 return USB_STOR_TRANSPORT_FAILED;
744 }
745
746 return result;
747}
748
Kim Phillipsb052b602012-10-29 13:34:32 +0000749static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000750{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100751 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000752 ccb *psrb;
753 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100754 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000755
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200756 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100757 status = USB_STOR_TRANSPORT_GOOD;
758 retry = 0;
759 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000760 /* issue the command */
761do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100762 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530763 debug("command / Data returned %d, status %lX\n",
764 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000765 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100766 if (us->protocol == US_PR_CBI) {
767 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000768 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100769 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530770 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000771 return status;
772 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100773 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
774 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
775 if (!us->ip_data) {
776 /* if the status is good, report it */
777 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530778 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000779 return status;
780 }
781 }
782 }
783 /* do we have to issue an auto request? */
784 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100785 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530786 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000787 us->transport_reset(us);
788 return USB_STOR_TRANSPORT_ERROR;
789 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100790 if ((us->protocol == US_PR_CBI) &&
791 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
792 (srb->cmd[0] == SCSI_INQUIRY))) {
793 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530794 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000795 return USB_STOR_TRANSPORT_GOOD;
796 }
797 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100798 memset(&psrb->cmd[0], 0, 12);
799 psrb->cmd[0] = SCSI_REQ_SENSE;
800 psrb->cmd[1] = srb->lun << 5;
801 psrb->cmd[4] = 18;
802 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200803 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100804 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000805 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100806 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530807 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000808 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100809 if (us->protocol == US_PR_CBI)
810 status = usb_stor_CBI_get_status(psrb, us);
811
812 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530813 debug(" AUTO REQUEST ERROR %ld\n",
814 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000815 return USB_STOR_TRANSPORT_ERROR;
816 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530817 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
818 srb->sense_buf[0], srb->sense_buf[2],
819 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000820 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100821 if ((srb->sense_buf[2] == 0) &&
822 (srb->sense_buf[12] == 0) &&
823 (srb->sense_buf[13] == 0)) {
824 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000825 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100826 }
827
wdenkaffae2b2002-08-17 09:36:01 +0000828 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100829 switch (srb->sense_buf[2]) {
830 case 0x01:
831 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000832 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000833 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100834 case 0x02:
835 /* Not Ready */
836 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
837 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
838 " 0x%02X (NOT READY)\n", srb->cmd[0],
839 srb->sense_buf[0], srb->sense_buf[2],
840 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000841 return USB_STOR_TRANSPORT_FAILED;
842 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000843 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000844 goto do_retry;
845 }
846 break;
847 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100848 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
849 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
850 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
851 srb->sense_buf[2], srb->sense_buf[12],
852 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000853 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100854 } else
wdenkde887eb2003-09-10 18:20:28 +0000855 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000856 break;
wdenkaffae2b2002-08-17 09:36:01 +0000857 }
858 return USB_STOR_TRANSPORT_FAILED;
859}
860
861
Michael Trimarchi956a4352008-12-10 15:52:06 +0100862static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000863{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100864 int retry, i;
865 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000866 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100867 memset(&srb->cmd[0], 0, 12);
868 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200869 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 srb->cmd[4] = 36;
871 srb->datalen = 36;
872 srb->cmdlen = 12;
873 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530874 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100875 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000876 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200877 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000878
Michael Trimarchi956a4352008-12-10 15:52:06 +0100879 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000880 printf("error in inquiry\n");
881 return -1;
882 }
883 return 0;
884}
885
Michael Trimarchi956a4352008-12-10 15:52:06 +0100886static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000887{
888 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000889
Michael Trimarchi956a4352008-12-10 15:52:06 +0100890 ptr = (char *)srb->pdata;
891 memset(&srb->cmd[0], 0, 12);
892 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200893 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100894 srb->cmd[4] = 18;
895 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200896 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100897 srb->cmdlen = 12;
898 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530899 debug("Request Sense returned %02X %02X %02X\n",
900 srb->sense_buf[2], srb->sense_buf[12],
901 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100902 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000903 return 0;
904}
905
Michael Trimarchi956a4352008-12-10 15:52:06 +0100906static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000907{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200908 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000909
wdenkaffae2b2002-08-17 09:36:01 +0000910 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 memset(&srb->cmd[0], 0, 12);
912 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200913 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914 srb->datalen = 0;
915 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200916 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
917 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000918 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200919 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100920 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800921 /*
922 * Check the Key Code Qualifier, if it matches
923 * "Not Ready - medium not present"
924 * (the sense Key equals 0x2 and the ASC is 0x3a)
925 * return immediately as the medium being absent won't change
926 * unless there is a user action.
927 */
928 if ((srb->sense_buf[2] == 0x02) &&
929 (srb->sense_buf[12] == 0x3a))
930 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000931 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100932 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000933
wdenkaffae2b2002-08-17 09:36:01 +0000934 return -1;
935}
936
Michael Trimarchi956a4352008-12-10 15:52:06 +0100937static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000938{
939 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100940 /* XXX retries */
941 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000942 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100943 memset(&srb->cmd[0], 0, 12);
944 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200945 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100946 srb->datalen = 8;
947 srb->cmdlen = 12;
948 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000949 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100950 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000951
wdenkaffae2b2002-08-17 09:36:01 +0000952 return -1;
953}
954
Michael Trimarchi956a4352008-12-10 15:52:06 +0100955static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
956 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000957{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100958 memset(&srb->cmd[0], 0, 12);
959 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200960 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100961 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
962 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
963 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
964 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
965 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
966 srb->cmd[8] = (unsigned char) blocks & 0xff;
967 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530968 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100969 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000970}
971
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530972static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
973 unsigned short blocks)
974{
975 memset(&srb->cmd[0], 0, 12);
976 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200977 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530978 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
979 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
980 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
981 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
982 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
983 srb->cmd[8] = (unsigned char) blocks & 0xff;
984 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530985 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530986 return ss->transport(srb, ss);
987}
988
wdenkaffae2b2002-08-17 09:36:01 +0000989
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +0200990#ifdef CONFIG_USB_BIN_FIXUP
991/*
992 * Some USB storage devices queried for SCSI identification data respond with
993 * binary strings, which if output to the console freeze the terminal. The
994 * workaround is to modify the vendor and product strings read from such
995 * device with proper values (as reported by 'usb info').
996 *
997 * Vendor and product length limits are taken from the definition of
998 * block_dev_desc_t in include/part.h.
999 */
1000static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1001 unsigned char vendor[],
1002 unsigned char product[]) {
1003 const unsigned char max_vendor_len = 40;
1004 const unsigned char max_product_len = 20;
1005 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001006 strncpy((char *)vendor, "SMSC", max_vendor_len);
1007 strncpy((char *)product, "Flash Media Cntrller",
1008 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001009 }
1010}
1011#endif /* CONFIG_USB_BIN_FIXUP */
1012
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001013unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001014 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001015{
Gabe Black7d077682012-10-12 14:26:07 +00001016 lbaint_t start, blks;
1017 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001018 unsigned short smallblks;
1019 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001020 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001021 int retry;
wdenk0e2874cb2004-03-02 14:05:39 +00001022 ccb *srb = &usb_ccb;
1023
1024 if (blkcnt == 0)
1025 return 0;
1026
1027 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001028 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001029 debug("\nusb_read: dev %d\n", device);
1030 dev = usb_dev_desc[device].priv;
1031 if (!dev) {
1032 debug("%s: No device\n", __func__);
1033 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001034 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001035 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001036
1037 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001038 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001039 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001040 start = blknr;
1041 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001042
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301043 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001044 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001045
wdenkaffae2b2002-08-17 09:36:01 +00001046 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001047 /* XXX need some comment here */
1048 retry = 2;
1049 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001050 if (blks > USB_MAX_XFER_BLK)
1051 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001052 else
1053 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001054retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001055 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001056 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001057 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1058 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001059 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301060 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001061 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001062 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001063 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001064 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001065 break;
1066 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001067 start += smallblks;
1068 blks -= smallblks;
1069 buf_addr += srb->datalen;
1070 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001071 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001072
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301073 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001074 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301075 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001076
wdenkaffae2b2002-08-17 09:36:01 +00001077 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001078 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001079 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001081}
1082
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001083unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001084 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301085{
Gabe Black7d077682012-10-12 14:26:07 +00001086 lbaint_t start, blks;
1087 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301088 unsigned short smallblks;
1089 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001090 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001091 int retry;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301092 ccb *srb = &usb_ccb;
1093
1094 if (blkcnt == 0)
1095 return 0;
1096
1097 device &= 0xff;
1098 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001099 debug("\nusb_write: dev %d\n", device);
1100 dev = usb_dev_desc[device].priv;
1101 if (!dev)
1102 return 0;
Kyle Moffett6540db02011-12-21 07:08:12 +00001103 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301104
1105 usb_disable_asynch(1); /* asynch transfer not allowed */
1106
1107 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001108 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301109 start = blknr;
1110 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301111
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301112 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001113 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301114
1115 do {
1116 /* If write fails retry for max retry count else
1117 * return with number of blocks written successfully.
1118 */
1119 retry = 2;
1120 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001121 if (blks > USB_MAX_XFER_BLK)
1122 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301123 else
1124 smallblks = (unsigned short) blks;
1125retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001126 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301127 usb_show_progress();
1128 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1129 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001130 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301131 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001132 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301133 if (retry--)
1134 goto retry_it;
1135 blkcnt -= blks;
1136 break;
1137 }
1138 start += smallblks;
1139 blks -= smallblks;
1140 buf_addr += srb->datalen;
1141 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001142 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301143
Simon Glassb43f7682014-10-15 04:38:38 -06001144 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1145 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301146
1147 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001148 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001149 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301150 return blkcnt;
1151
1152}
wdenkaffae2b2002-08-17 09:36:01 +00001153
1154/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001155int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1156 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001157{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001158 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001159 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301160 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001161 unsigned int flags = 0;
1162
1163 int protocol = 0;
1164 int subclass = 0;
1165
wdenkaffae2b2002-08-17 09:36:01 +00001166 /* let's examine the device now */
1167 iface = &dev->config.if_desc[ifnum];
1168
1169#if 0
1170 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301171 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001172 dev->descriptor.idProduct);
1173
1174 if ((dev->descriptor.idVendor) == 0x066b &&
1175 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301176 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001177 protocol = US_PR_CB;
1178 subclass = US_SC_UFI; /* an assumption */
1179 }
1180#endif
1181
1182 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001183 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1184 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1185 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001186 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001187 /* if it's not a mass storage, we go no further */
1188 return 0;
1189 }
1190
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001191 memset(ss, 0, sizeof(struct us_data));
1192
wdenkaffae2b2002-08-17 09:36:01 +00001193 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301194 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001195
1196 /* Initialize the us_data structure with some useful info */
1197 ss->flags = flags;
1198 ss->ifnum = ifnum;
1199 ss->pusb_dev = dev;
1200 ss->attention_done = 0;
1201
1202 /* If the device has subclass and protocol, then use that. Otherwise,
1203 * take data from the specific interface.
1204 */
1205 if (subclass) {
1206 ss->subclass = subclass;
1207 ss->protocol = protocol;
1208 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001209 ss->subclass = iface->desc.bInterfaceSubClass;
1210 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001211 }
1212
1213 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301214 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001215 switch (ss->protocol) {
1216 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301217 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001218 ss->transport = usb_stor_CB_transport;
1219 ss->transport_reset = usb_stor_CB_reset;
1220 break;
1221
1222 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301223 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001224 ss->transport = usb_stor_CB_transport;
1225 ss->transport_reset = usb_stor_CB_reset;
1226 break;
wdenkde887eb2003-09-10 18:20:28 +00001227 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301228 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001229 ss->transport = usb_stor_BBB_transport;
1230 ss->transport_reset = usb_stor_BBB_reset;
1231 break;
wdenkaffae2b2002-08-17 09:36:01 +00001232 default:
wdenk5f495752004-02-26 23:46:20 +00001233 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001234 return 0;
1235 break;
1236 }
1237
1238 /*
1239 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1240 * An optional interrupt is OK (necessary for CBI protocol).
1241 * We will ignore any others.
1242 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001243 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301244 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001245 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301246 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001247 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301248 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1249 ss->ep_in = ep_desc->bEndpointAddress &
1250 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001251 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001252 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301253 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001254 USB_ENDPOINT_NUMBER_MASK;
1255 }
1256
1257 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301258 if ((ep_desc->bmAttributes &
1259 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1260 ss->ep_int = ep_desc->bEndpointAddress &
1261 USB_ENDPOINT_NUMBER_MASK;
1262 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001263 }
1264 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301265 debug("Endpoints In %d Out %d Int %d\n",
1266 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001267
1268 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001269 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001270 !ss->ep_in || !ss->ep_out ||
1271 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301272 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001273 return 0;
1274 }
1275 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001276 /* We only handle certain protocols. Currently, these are
1277 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001278 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001279 */
wdenk5f495752004-02-26 23:46:20 +00001280 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1281 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001282 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001283 return 0;
1284 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001285 if (ss->ep_int) {
1286 /* we had found an interrupt endpoint, prepare irq pipe
1287 * set up the IRQ pipe and handler
1288 */
wdenkaffae2b2002-08-17 09:36:01 +00001289 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1290 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1291 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001292 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001293 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001294 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001295 return 1;
1296}
1297
Michael Trimarchi956a4352008-12-10 15:52:06 +01001298int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1299 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001300{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001301 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001302 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1303 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1304 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001305 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001306
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001307 pccb->pdata = usb_stor_buf;
1308
1309 dev_desc->target = dev->devnum;
1310 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301311 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001312
Simon Glass78330d62015-03-25 12:22:12 -06001313 if (usb_inquiry(pccb, ss)) {
1314 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001315 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001316 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001317
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001318 perq = usb_stor_buf[0];
1319 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001320
Soeren Moche4828002014-11-08 07:02:14 +01001321 /*
1322 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1323 * they would not respond to test_unit_ready .
1324 */
1325 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001326 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001327 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001328 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001329 if ((modi&0x80) == 0x80) {
1330 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001331 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001332 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001333 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1334 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1335 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001336 dev_desc->vendor[8] = 0;
1337 dev_desc->product[16] = 0;
1338 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001339#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001340 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1341 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001342#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301343 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1344 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001345 if (usb_test_unit_ready(pccb, ss)) {
1346 printf("Device NOT ready\n"
1347 " Request Sense returned %02X %02X %02X\n",
1348 pccb->sense_buf[2], pccb->sense_buf[12],
1349 pccb->sense_buf[13]);
1350 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001351 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001352 return 1;
1353 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001354 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001355 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001356 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001357 memset(pccb->pdata, 0, 8);
1358 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001359 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001360 cap[0] = 2880;
1361 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001362 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001363 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001364 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001365#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001366 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1367 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001368
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001369 cap[0] = cpu_to_be32(cap[0]);
1370 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001371#endif
1372
1373 capacity = be32_to_cpu(cap[0]) + 1;
1374 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001375
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001376 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1377 dev_desc->lba = capacity;
1378 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001379 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001380 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301381 debug(" address %d\n", dev_desc->target);
1382 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001383
1384 init_part(dev_desc);
1385
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301386 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001387 return 1;
1388}