blob: 5ff4337de07bf66d94e9db7785dd61f89a737588 [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>
Simon Glass332a9b62015-03-25 12:22:14 -060037#include <mapmem.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020038#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000039#include <asm/processor.h>
40
Grant Likelyffc2dd72007-02-20 09:04:34 +010041#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000042#include <usb.h>
43
wdenk5f495752004-02-26 23:46:20 +000044#undef BBB_COMDAT_TRACE
45#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000046
wdenkaffae2b2002-08-17 09:36:01 +000047#include <scsi.h>
48/* direction table -- this indicates the direction of the data
49 * transfer for each command code -- a 1 indicates input
50 */
Mike Frysinger165522b2010-10-20 07:16:04 -040051static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000052 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
53 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
56};
57#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
58
Puneet Saxena6c9bb602012-04-03 14:56:06 +053059static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchi956a4352008-12-10 15:52:06 +010060static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000061
wdenkaffae2b2002-08-17 09:36:01 +000062#define USB_MAX_STOR_DEV 5
Michael Trimarchi956a4352008-12-10 15:52:06 +010063static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000064
65static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
66
67struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +010068typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
69typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000070
71struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010072 struct usb_device *pusb_dev; /* this usb_device */
73
74 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020075# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010076 unsigned char ifnum; /* interface number */
77 unsigned char ep_in; /* in endpoint */
78 unsigned char ep_out; /* out ....... */
79 unsigned char ep_int; /* interrupt . */
80 unsigned char subclass; /* as in overview */
81 unsigned char protocol; /* .............. */
82 unsigned char attention_done; /* force attn on first cmd */
83 unsigned short ip_data; /* interrupt data */
84 int action; /* what to do */
85 int ip_wanted; /* needed */
86 int *irq_handle; /* for USB int requests */
87 unsigned int irqpipe; /* pipe for release_irq */
88 unsigned char irqmaxp; /* max packed for irq Pipe */
89 unsigned char irqinterval; /* Intervall for IRQ Pipe */
90 ccb *srb; /* current srb */
91 trans_reset transport_reset; /* reset routine */
92 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000093};
94
Benoît Thébaudeau938051f2012-08-10 18:26:50 +020095#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +000096/*
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +020097 * The U-Boot EHCI driver can handle any transfer length as long as there is
98 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
99 * limited to 65535 blocks.
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000100 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200101#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200102#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200103#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200104#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000105
wdenkaffae2b2002-08-17 09:36:01 +0000106static struct us_data usb_stor[USB_MAX_STOR_DEV];
107
108
wdenk5f495752004-02-26 23:46:20 +0000109#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000110#define USB_STOR_TRANSPORT_FAILED -1
111#define USB_STOR_TRANSPORT_ERROR -2
112
Michael Trimarchi956a4352008-12-10 15:52:06 +0100113int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
114 block_dev_desc_t *dev_desc);
115int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
116 struct us_data *ss);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200117unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000118 lbaint_t blkcnt, void *buffer);
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200119unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +0000120 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000121struct usb_device * usb_get_dev_index(int index);
122void uhci_show_temp_int_td(void);
123
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000124#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000125block_dev_desc_t *usb_stor_get_dev(int index)
126{
Kim B. Heino300ea512010-03-12 15:46:56 +0200127 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000128}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000129#endif
wdenkaffae2b2002-08-17 09:36:01 +0000130
Kim Phillipsb052b602012-10-29 13:34:32 +0000131static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000132{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200133 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000134}
135
Michael Trimarchi956a4352008-12-10 15:52:06 +0100136/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200137 * show info on storage devices; 'usb start/init' must be invoked earlier
138 * as we only retrieve structures populated during devices initialization
139 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100140int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200141{
142 int i;
143
Aras Vaichas7ede1862008-03-25 12:09:07 +1100144 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200145 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100146 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200147 dev_print(&usb_dev_desc[i]);
148 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100149 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100150 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700151
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100152 printf("No storage devices, perhaps not 'usb start'ed..?\n");
153 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200154}
155
Ludovic Courtès134396c2010-10-05 22:04:26 +0200156static unsigned int usb_get_max_lun(struct us_data *us)
157{
158 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530159 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200160 len = usb_control_msg(us->pusb_dev,
161 usb_rcvctrlpipe(us->pusb_dev, 0),
162 US_BBB_GET_MAX_LUN,
163 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
164 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530165 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200166 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530167 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530168 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200169}
170
Michael Trimarchi956a4352008-12-10 15:52:06 +0100171/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200172 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000173 * to the user if mode = 1
174 * returns current device or -1 if no
175 */
176int usb_stor_scan(int mode)
177{
Simon Glass0f50b162015-04-16 17:27:34 -0600178 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000179 struct usb_device *dev;
180
Michael Trimarchi956a4352008-12-10 15:52:06 +0100181 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200182 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100183
wdenkaffae2b2002-08-17 09:36:01 +0000184 usb_disable_asynch(1); /* asynch transfer not allowed */
185
Michael Trimarchi956a4352008-12-10 15:52:06 +0100186 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
187 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100188 usb_dev_desc[i].if_type = IF_TYPE_USB;
189 usb_dev_desc[i].dev = i;
190 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200191 usb_dev_desc[i].target = 0xff;
192 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100193 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530194 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000195 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200196
Michael Trimarchi956a4352008-12-10 15:52:06 +0100197 usb_max_devs = 0;
198 for (i = 0; i < USB_MAX_DEVICE; i++) {
199 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530200 debug("i=%d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100201 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100202 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100203
Simon Glass0f50b162015-04-16 17:27:34 -0600204 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
205 /* OK, it's a storage device. Iterate over its LUNs
206 * and populate `usb_dev_desc'.
207 */
208 int lun, max_lun, start = usb_max_devs;
Franck Jullien20f3eb82015-03-04 21:07:00 +0100209
Simon Glass0f50b162015-04-16 17:27:34 -0600210 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
211 for (lun = 0;
212 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
213 lun++) {
214 usb_dev_desc[usb_max_devs].lun = lun;
215 if (usb_stor_get_info(dev, &usb_stor[start],
216 &usb_dev_desc[usb_max_devs]) == 1) {
217 usb_max_devs++;
218 }
219 }
220 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100221 /* if storage device */
222 if (usb_max_devs == USB_MAX_STOR_DEV) {
223 printf("max USB Storage Device reached: %d stopping\n",
224 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000225 break;
226 }
227 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200228
wdenkaffae2b2002-08-17 09:36:01 +0000229 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200230 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100231 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000232 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100233 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000234}
235
236static int usb_stor_irq(struct usb_device *dev)
237{
238 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100239 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000240
Michael Trimarchi956a4352008-12-10 15:52:06 +0100241 if (us->ip_wanted)
242 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000243 return 0;
244}
245
246
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530247#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000248
Michael Trimarchi956a4352008-12-10 15:52:06 +0100249static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000250{
251 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100252 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
253 for (i = 0; i < 12; i++)
254 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000255 printf("\n");
256}
257
258static void display_int_status(unsigned long tmp)
259{
260 printf("Status: %s %s %s %s %s %s %s\n",
261 (tmp & USB_ST_ACTIVE) ? "Active" : "",
262 (tmp & USB_ST_STALLED) ? "Stalled" : "",
263 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
264 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
265 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
266 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
267 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
268}
269#endif
270/***********************************************************************
271 * Data transfer routines
272 ***********************************************************************/
273
274static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
275{
276 int max_size;
277 int this_xfer;
278 int result;
279 int partial;
280 int maxtry;
281 int stat;
282
283 /* determine the maximum packet size for these transfers */
284 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
285
286 /* while we have data left to transfer */
287 while (length) {
288
289 /* calculate how long this will be -- maximum or a remainder */
290 this_xfer = length > max_size ? max_size : length;
291 length -= this_xfer;
292
293 /* setup the retry counter */
294 maxtry = 10;
295
296 /* set up the transfer loop */
297 do {
298 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600299 debug("Bulk xfer 0x%lx(%d) try #%d\n",
300 (ulong)map_to_sysmem(buf), this_xfer,
301 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000302 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100303 this_xfer, &partial,
304 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530305 debug("bulk_msg returned %d xferred %d/%d\n",
306 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100307 if (us->pusb_dev->status != 0) {
308 /* if we stall, we need to clear it before
309 * we go on
310 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530311#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000312 display_int_status(us->pusb_dev->status);
313#endif
314 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530315 debug("stalled ->clearing endpoint" \
316 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000317 stat = us->pusb_dev->status;
318 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100319 us->pusb_dev->status = stat;
320 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530321 debug("bulk transferred" \
322 "with error %lX," \
323 " but data ok\n",
324 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000325 return 0;
326 }
327 else
328 return result;
329 }
330 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530331 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000332 return result;
333 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530334 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100335 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530336 debug(" %ld, but data ok\n",
337 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000338 return 0;
339 }
340 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530341 debug(" %ld, data %d\n",
342 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000343 if (!maxtry--)
344 return result;
345 }
346 /* update to show what data was transferred */
347 this_xfer -= partial;
348 buf += partial;
349 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100350 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000351 }
352
353 /* if we get here, we're done and successful */
354 return 0;
355}
356
wdenkde887eb2003-09-10 18:20:28 +0000357static int usb_stor_BBB_reset(struct us_data *us)
358{
359 int result;
360 unsigned int pipe;
361
362 /*
363 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
364 *
365 * For Reset Recovery the host shall issue in the following order:
366 * a) a Bulk-Only Mass Storage Reset
367 * b) a Clear Feature HALT to the Bulk-In endpoint
368 * c) a Clear Feature HALT to the Bulk-Out endpoint
369 *
370 * This is done in 3 steps.
371 *
372 * If the reset doesn't succeed, the device should be port reset.
373 *
374 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
375 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530376 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100377 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
378 US_BBB_RESET,
379 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000380 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200381
Michael Trimarchi956a4352008-12-10 15:52:06 +0100382 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530383 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000384 return -1;
385 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200386
wdenkde887eb2003-09-10 18:20:28 +0000387 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000388 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530389 debug("BBB_reset result %d: status %lX reset\n",
390 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000391 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
392 result = usb_clear_halt(us->pusb_dev, pipe);
393 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000394 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530395 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
396 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000397 /* long wait for reset */
398 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
399 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000400 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530401 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
402 result, us->pusb_dev->status);
403 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000404 return 0;
405}
406
wdenkaffae2b2002-08-17 09:36:01 +0000407/* FIXME: this reset function doesn't really reset the port, and it
408 * should. Actually it should probably do what it's doing here, and
409 * reset the port physically
410 */
411static int usb_stor_CB_reset(struct us_data *us)
412{
413 unsigned char cmd[12];
414 int result;
415
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530416 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100417 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000418 cmd[0] = SCSI_SEND_DIAG;
419 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100420 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
421 US_CBI_ADSC,
422 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
423 0, us->ifnum, cmd, sizeof(cmd),
424 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000425
426 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000427 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530428 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
429 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000430 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
431 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
432
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530433 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000434 return 0;
435}
436
wdenkde887eb2003-09-10 18:20:28 +0000437/*
438 * Set up the command for a BBB device. Note that the actual SCSI
439 * command is copied into cbw.CBWCDB.
440 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000441static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000442{
443 int result;
444 int actlen;
445 int dir_in;
446 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600447 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000448
449 dir_in = US_DIRECTION(srb->cmd[0]);
450
451#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530452 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100453 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
454 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000455 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100456 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000457 printf("cmd[%d] %#x ", result, srb->cmd[result]);
458 printf("\n");
459 }
460#endif
461 /* sanity checks */
462 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530463 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000464 return -1;
465 }
466
467 /* always OUT to the ep */
468 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
469
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530470 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
471 cbw->dCBWTag = cpu_to_le32(CBWTag++);
472 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
473 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
474 cbw->bCBWLUN = srb->lun;
475 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000476 /* copy the command data into the CBW command data buffer */
477 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300478
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530479 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
480 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100481 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000482 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530483 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000484 return result;
485}
486
wdenkaffae2b2002-08-17 09:36:01 +0000487/* FIXME: we also need a CBI_command which sets up the completion
488 * interrupt, and waits for it
489 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000490static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000491{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200492 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100493 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000494 unsigned int pipe;
495 unsigned long status;
496
Michael Trimarchi956a4352008-12-10 15:52:06 +0100497 retry = 5;
498 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000499
Michael Trimarchi956a4352008-12-10 15:52:06 +0100500 if (dir_in)
501 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
502 else
503 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
504
505 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530506 debug("CBI gets a command: Try %d\n", 5 - retry);
507#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000508 usb_show_srb(srb);
509#endif
510 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100511 result = usb_control_msg(us->pusb_dev,
512 usb_sndctrlpipe(us->pusb_dev , 0),
513 US_CBI_ADSC,
514 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000515 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100516 srb->cmd, srb->cmdlen,
517 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530518 debug("CB_transport: control msg returned %d, status %lX\n",
519 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000520 /* check the return code for the command */
521 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100522 if (us->pusb_dev->status & USB_ST_STALLED) {
523 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530524 debug(" stall during command found," \
525 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100526 usb_clear_halt(us->pusb_dev,
527 usb_sndctrlpipe(us->pusb_dev, 0));
528 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000529 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530530 debug(" error during command %02X" \
531 " Stat = %lX\n", srb->cmd[0],
532 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000533 return result;
534 }
535 /* transfer the data payload for this command, if one exists*/
536
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530537 debug("CB_transport: control msg returned %d," \
538 " direction is %s to go 0x%lx\n", result,
539 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000540 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100541 result = us_one_transfer(us, pipe, (char *)srb->pdata,
542 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530543 debug("CBI attempted to transfer data," \
544 " result is %d status %lX, len %d\n",
545 result, us->pusb_dev->status,
546 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100547 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000548 break;
549 } /* if (srb->datalen) */
550 else
551 break;
552 }
553 /* return result */
554
555 return result;
556}
557
558
Kim Phillipsb052b602012-10-29 13:34:32 +0000559static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000560{
561 int timeout;
562
wdenk5f495752004-02-26 23:46:20 +0000563 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100564 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000565 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
566 timeout = 1000;
567 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300568 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000569 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000570 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000571 }
572 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100573 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000574 us->ip_wanted = 0;
575 return USB_STOR_TRANSPORT_ERROR;
576 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530577 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
578 us->ip_data, us->pusb_dev->irq_act_len,
579 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000580 /* UFI gives us ASC and ASCQ, like a request sense */
581 if (us->subclass == US_SC_UFI) {
582 if (srb->cmd[0] == SCSI_REQ_SENSE ||
583 srb->cmd[0] == SCSI_INQUIRY)
584 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000585 else if (us->ip_data)
586 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000587 else
wdenk5f495752004-02-26 23:46:20 +0000588 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000589 }
590 /* otherwise, we interpret the data normally */
591 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000592 case 0x0001:
593 return USB_STOR_TRANSPORT_GOOD;
594 case 0x0002:
595 return USB_STOR_TRANSPORT_FAILED;
596 default:
597 return USB_STOR_TRANSPORT_ERROR;
598 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000599 return USB_STOR_TRANSPORT_ERROR;
600}
601
602#define USB_TRANSPORT_UNKNOWN_RETRY 5
603#define USB_TRANSPORT_NOT_READY_RETRY 10
604
wdenkde887eb2003-09-10 18:20:28 +0000605/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000606static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000607{
608 int result;
609
610 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100611 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000612 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000613 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000614 return result;
615}
616
Kim Phillipsb052b602012-10-29 13:34:32 +0000617static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000618{
619 int result, retry;
620 int dir_in;
621 int actlen, data_actlen;
622 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600623 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000624#ifdef BBB_XPORT_TRACE
625 unsigned char *ptr;
626 int index;
627#endif
628
629 dir_in = US_DIRECTION(srb->cmd[0]);
630
631 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530632 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000633 result = usb_stor_BBB_comdat(srb, us);
634 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530635 debug("failed to send CBW status %ld\n",
636 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000637 usb_stor_BBB_reset(us);
638 return USB_STOR_TRANSPORT_FAILED;
639 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200640 if (!(us->flags & USB_READY))
641 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000642 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
643 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
644 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000645 data_actlen = 0;
646 /* no data, go immediately to the STATUS phase */
647 if (srb->datalen == 0)
648 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530649 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000650 if (dir_in)
651 pipe = pipein;
652 else
653 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300654
Michael Trimarchi956a4352008-12-10 15:52:06 +0100655 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
656 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000657 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100658 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530659 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000660 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100661 result = usb_stor_BBB_clear_endpt_stall(us,
662 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000663 if (result >= 0)
664 /* continue on to STATUS phase */
665 goto st;
666 }
667 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530668 debug("usb_bulk_msg error status %ld\n",
669 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000670 usb_stor_BBB_reset(us);
671 return USB_STOR_TRANSPORT_FAILED;
672 }
673#ifdef BBB_XPORT_TRACE
674 for (index = 0; index < data_actlen; index++)
675 printf("pdata[%d] %#x ", index, srb->pdata[index]);
676 printf("\n");
677#endif
678 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100679st:
wdenkde887eb2003-09-10 18:20:28 +0000680 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100681again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530682 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530683 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200684 &actlen, USB_CNTL_TIMEOUT*5);
685
wdenkde887eb2003-09-10 18:20:28 +0000686 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100687 if ((result < 0) && (retry < 1) &&
688 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530689 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000690 /* clear the STALL on the endpoint */
691 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
692 if (result >= 0 && (retry++ < 1))
693 /* do a retry */
694 goto again;
695 }
696 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530697 debug("usb_bulk_msg error status %ld\n",
698 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000699 usb_stor_BBB_reset(us);
700 return USB_STOR_TRANSPORT_FAILED;
701 }
702#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530703 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000704 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
705 printf("ptr[%d] %#x ", index, ptr[index]);
706 printf("\n");
707#endif
708 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530709 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000710 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
711 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530712 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530713 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000714 usb_stor_BBB_reset(us);
715 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530716 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530717 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000718 usb_stor_BBB_reset(us);
719 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530720 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530721 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000722 usb_stor_BBB_reset(us);
723 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530724 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530725 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000726 usb_stor_BBB_reset(us);
727 return USB_STOR_TRANSPORT_FAILED;
728 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530729 debug("transferred %dB instead of %ldB\n",
730 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000731 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530732 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530733 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000734 return USB_STOR_TRANSPORT_FAILED;
735 }
736
737 return result;
738}
739
Kim Phillipsb052b602012-10-29 13:34:32 +0000740static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000741{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100742 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000743 ccb *psrb;
744 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100745 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000746
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200747 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100748 status = USB_STOR_TRANSPORT_GOOD;
749 retry = 0;
750 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000751 /* issue the command */
752do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100753 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530754 debug("command / Data returned %d, status %lX\n",
755 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000756 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100757 if (us->protocol == US_PR_CBI) {
758 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000759 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100760 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530761 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000762 return status;
763 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100764 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
765 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
766 if (!us->ip_data) {
767 /* if the status is good, report it */
768 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530769 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000770 return status;
771 }
772 }
773 }
774 /* do we have to issue an auto request? */
775 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100776 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530777 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000778 us->transport_reset(us);
779 return USB_STOR_TRANSPORT_ERROR;
780 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100781 if ((us->protocol == US_PR_CBI) &&
782 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
783 (srb->cmd[0] == SCSI_INQUIRY))) {
784 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530785 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000786 return USB_STOR_TRANSPORT_GOOD;
787 }
788 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100789 memset(&psrb->cmd[0], 0, 12);
790 psrb->cmd[0] = SCSI_REQ_SENSE;
791 psrb->cmd[1] = srb->lun << 5;
792 psrb->cmd[4] = 18;
793 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200794 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100795 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000796 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100797 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530798 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000799 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100800 if (us->protocol == US_PR_CBI)
801 status = usb_stor_CBI_get_status(psrb, us);
802
803 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530804 debug(" AUTO REQUEST ERROR %ld\n",
805 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000806 return USB_STOR_TRANSPORT_ERROR;
807 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530808 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
809 srb->sense_buf[0], srb->sense_buf[2],
810 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000811 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100812 if ((srb->sense_buf[2] == 0) &&
813 (srb->sense_buf[12] == 0) &&
814 (srb->sense_buf[13] == 0)) {
815 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000816 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100817 }
818
wdenkaffae2b2002-08-17 09:36:01 +0000819 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100820 switch (srb->sense_buf[2]) {
821 case 0x01:
822 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000823 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000824 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100825 case 0x02:
826 /* Not Ready */
827 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
828 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
829 " 0x%02X (NOT READY)\n", srb->cmd[0],
830 srb->sense_buf[0], srb->sense_buf[2],
831 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000832 return USB_STOR_TRANSPORT_FAILED;
833 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000834 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000835 goto do_retry;
836 }
837 break;
838 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100839 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
840 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
841 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
842 srb->sense_buf[2], srb->sense_buf[12],
843 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000844 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100845 } else
wdenkde887eb2003-09-10 18:20:28 +0000846 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000847 break;
wdenkaffae2b2002-08-17 09:36:01 +0000848 }
849 return USB_STOR_TRANSPORT_FAILED;
850}
851
852
Michael Trimarchi956a4352008-12-10 15:52:06 +0100853static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000854{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100855 int retry, i;
856 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000857 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100858 memset(&srb->cmd[0], 0, 12);
859 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200860 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100861 srb->cmd[4] = 36;
862 srb->datalen = 36;
863 srb->cmdlen = 12;
864 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530865 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100866 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000867 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200868 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000869
Michael Trimarchi956a4352008-12-10 15:52:06 +0100870 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000871 printf("error in inquiry\n");
872 return -1;
873 }
874 return 0;
875}
876
Michael Trimarchi956a4352008-12-10 15:52:06 +0100877static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000878{
879 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000880
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 ptr = (char *)srb->pdata;
882 memset(&srb->cmd[0], 0, 12);
883 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200884 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100885 srb->cmd[4] = 18;
886 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200887 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100888 srb->cmdlen = 12;
889 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530890 debug("Request Sense returned %02X %02X %02X\n",
891 srb->sense_buf[2], srb->sense_buf[12],
892 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100893 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000894 return 0;
895}
896
Michael Trimarchi956a4352008-12-10 15:52:06 +0100897static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000898{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200899 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000900
wdenkaffae2b2002-08-17 09:36:01 +0000901 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100902 memset(&srb->cmd[0], 0, 12);
903 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200904 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100905 srb->datalen = 0;
906 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200907 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
908 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000909 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200910 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800912 /*
913 * Check the Key Code Qualifier, if it matches
914 * "Not Ready - medium not present"
915 * (the sense Key equals 0x2 and the ASC is 0x3a)
916 * return immediately as the medium being absent won't change
917 * unless there is a user action.
918 */
919 if ((srb->sense_buf[2] == 0x02) &&
920 (srb->sense_buf[12] == 0x3a))
921 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000922 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100923 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000924
wdenkaffae2b2002-08-17 09:36:01 +0000925 return -1;
926}
927
Michael Trimarchi956a4352008-12-10 15:52:06 +0100928static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000929{
930 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100931 /* XXX retries */
932 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000933 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100934 memset(&srb->cmd[0], 0, 12);
935 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200936 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100937 srb->datalen = 8;
938 srb->cmdlen = 12;
939 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000940 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100941 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000942
wdenkaffae2b2002-08-17 09:36:01 +0000943 return -1;
944}
945
Michael Trimarchi956a4352008-12-10 15:52:06 +0100946static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
947 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000948{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100949 memset(&srb->cmd[0], 0, 12);
950 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200951 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100952 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
953 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
954 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
955 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
956 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
957 srb->cmd[8] = (unsigned char) blocks & 0xff;
958 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530959 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100960 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000961}
962
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530963static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
964 unsigned short blocks)
965{
966 memset(&srb->cmd[0], 0, 12);
967 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200968 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530969 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
970 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
971 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
972 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
973 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
974 srb->cmd[8] = (unsigned char) blocks & 0xff;
975 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530976 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530977 return ss->transport(srb, ss);
978}
979
wdenkaffae2b2002-08-17 09:36:01 +0000980
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +0200981#ifdef CONFIG_USB_BIN_FIXUP
982/*
983 * Some USB storage devices queried for SCSI identification data respond with
984 * binary strings, which if output to the console freeze the terminal. The
985 * workaround is to modify the vendor and product strings read from such
986 * device with proper values (as reported by 'usb info').
987 *
988 * Vendor and product length limits are taken from the definition of
989 * block_dev_desc_t in include/part.h.
990 */
991static void usb_bin_fixup(struct usb_device_descriptor descriptor,
992 unsigned char vendor[],
993 unsigned char product[]) {
994 const unsigned char max_vendor_len = 40;
995 const unsigned char max_product_len = 20;
996 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100997 strncpy((char *)vendor, "SMSC", max_vendor_len);
998 strncpy((char *)product, "Flash Media Cntrller",
999 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001000 }
1001}
1002#endif /* CONFIG_USB_BIN_FIXUP */
1003
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001004unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001005 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001006{
Gabe Black7d077682012-10-12 14:26:07 +00001007 lbaint_t start, blks;
1008 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001009 unsigned short smallblks;
1010 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001011 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001012 int retry;
wdenk0e2874cb2004-03-02 14:05:39 +00001013 ccb *srb = &usb_ccb;
1014
1015 if (blkcnt == 0)
1016 return 0;
1017
1018 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001019 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001020 debug("\nusb_read: dev %d\n", device);
1021 dev = usb_dev_desc[device].priv;
1022 if (!dev) {
1023 debug("%s: No device\n", __func__);
1024 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001025 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001026 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001027
1028 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001029 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001030 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001031 start = blknr;
1032 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001033
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301034 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001035 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001036
wdenkaffae2b2002-08-17 09:36:01 +00001037 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001038 /* XXX need some comment here */
1039 retry = 2;
1040 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001041 if (blks > USB_MAX_XFER_BLK)
1042 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001043 else
1044 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001045retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001046 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001047 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001048 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1049 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001050 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301051 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001052 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001053 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001054 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001055 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001056 break;
1057 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001058 start += smallblks;
1059 blks -= smallblks;
1060 buf_addr += srb->datalen;
1061 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001062 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001063
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301064 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001065 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301066 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001067
wdenkaffae2b2002-08-17 09:36:01 +00001068 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001069 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001070 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001071 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001072}
1073
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +02001074unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Black7d077682012-10-12 14:26:07 +00001075 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301076{
Gabe Black7d077682012-10-12 14:26:07 +00001077 lbaint_t start, blks;
1078 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301079 unsigned short smallblks;
1080 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001081 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001082 int retry;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301083 ccb *srb = &usb_ccb;
1084
1085 if (blkcnt == 0)
1086 return 0;
1087
1088 device &= 0xff;
1089 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001090 debug("\nusb_write: dev %d\n", device);
1091 dev = usb_dev_desc[device].priv;
1092 if (!dev)
1093 return 0;
Kyle Moffett6540db02011-12-21 07:08:12 +00001094 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301095
1096 usb_disable_asynch(1); /* asynch transfer not allowed */
1097
1098 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001099 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301100 start = blknr;
1101 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301102
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301103 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001104 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301105
1106 do {
1107 /* If write fails retry for max retry count else
1108 * return with number of blocks written successfully.
1109 */
1110 retry = 2;
1111 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001112 if (blks > USB_MAX_XFER_BLK)
1113 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301114 else
1115 smallblks = (unsigned short) blks;
1116retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001117 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301118 usb_show_progress();
1119 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1120 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001121 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301122 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001123 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301124 if (retry--)
1125 goto retry_it;
1126 blkcnt -= blks;
1127 break;
1128 }
1129 start += smallblks;
1130 blks -= smallblks;
1131 buf_addr += srb->datalen;
1132 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001133 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301134
Simon Glassb43f7682014-10-15 04:38:38 -06001135 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1136 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301137
1138 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001139 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001140 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301141 return blkcnt;
1142
1143}
wdenkaffae2b2002-08-17 09:36:01 +00001144
1145/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001146int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1147 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001148{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001149 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001150 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301151 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001152 unsigned int flags = 0;
1153
1154 int protocol = 0;
1155 int subclass = 0;
1156
wdenkaffae2b2002-08-17 09:36:01 +00001157 /* let's examine the device now */
1158 iface = &dev->config.if_desc[ifnum];
1159
1160#if 0
1161 /* this is the place to patch some storage devices */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301162 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchi956a4352008-12-10 15:52:06 +01001163 dev->descriptor.idProduct);
1164
1165 if ((dev->descriptor.idVendor) == 0x066b &&
1166 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301167 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001168 protocol = US_PR_CB;
1169 subclass = US_SC_UFI; /* an assumption */
1170 }
1171#endif
1172
1173 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001174 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1175 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1176 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001177 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001178 /* if it's not a mass storage, we go no further */
1179 return 0;
1180 }
1181
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001182 memset(ss, 0, sizeof(struct us_data));
1183
wdenkaffae2b2002-08-17 09:36:01 +00001184 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301185 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001186
1187 /* Initialize the us_data structure with some useful info */
1188 ss->flags = flags;
1189 ss->ifnum = ifnum;
1190 ss->pusb_dev = dev;
1191 ss->attention_done = 0;
1192
1193 /* If the device has subclass and protocol, then use that. Otherwise,
1194 * take data from the specific interface.
1195 */
1196 if (subclass) {
1197 ss->subclass = subclass;
1198 ss->protocol = protocol;
1199 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001200 ss->subclass = iface->desc.bInterfaceSubClass;
1201 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001202 }
1203
1204 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301205 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001206 switch (ss->protocol) {
1207 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301208 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001209 ss->transport = usb_stor_CB_transport;
1210 ss->transport_reset = usb_stor_CB_reset;
1211 break;
1212
1213 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301214 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001215 ss->transport = usb_stor_CB_transport;
1216 ss->transport_reset = usb_stor_CB_reset;
1217 break;
wdenkde887eb2003-09-10 18:20:28 +00001218 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301219 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001220 ss->transport = usb_stor_BBB_transport;
1221 ss->transport_reset = usb_stor_BBB_reset;
1222 break;
wdenkaffae2b2002-08-17 09:36:01 +00001223 default:
wdenk5f495752004-02-26 23:46:20 +00001224 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001225 return 0;
1226 break;
1227 }
1228
1229 /*
1230 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1231 * An optional interrupt is OK (necessary for CBI protocol).
1232 * We will ignore any others.
1233 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001234 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301235 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001236 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301237 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001238 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301239 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1240 ss->ep_in = ep_desc->bEndpointAddress &
1241 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001242 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001243 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301244 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001245 USB_ENDPOINT_NUMBER_MASK;
1246 }
1247
1248 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301249 if ((ep_desc->bmAttributes &
1250 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1251 ss->ep_int = ep_desc->bEndpointAddress &
1252 USB_ENDPOINT_NUMBER_MASK;
1253 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001254 }
1255 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301256 debug("Endpoints In %d Out %d Int %d\n",
1257 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001258
1259 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001260 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001261 !ss->ep_in || !ss->ep_out ||
1262 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301263 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001264 return 0;
1265 }
1266 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001267 /* We only handle certain protocols. Currently, these are
1268 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001269 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001270 */
wdenk5f495752004-02-26 23:46:20 +00001271 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1272 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001273 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001274 return 0;
1275 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001276 if (ss->ep_int) {
1277 /* we had found an interrupt endpoint, prepare irq pipe
1278 * set up the IRQ pipe and handler
1279 */
wdenkaffae2b2002-08-17 09:36:01 +00001280 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1281 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1282 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001283 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001284 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001285 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001286 return 1;
1287}
1288
Michael Trimarchi956a4352008-12-10 15:52:06 +01001289int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1290 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001291{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001292 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001293 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1294 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1295 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001296 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001297
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001298 pccb->pdata = usb_stor_buf;
1299
1300 dev_desc->target = dev->devnum;
1301 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301302 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001303
Simon Glass78330d62015-03-25 12:22:12 -06001304 if (usb_inquiry(pccb, ss)) {
1305 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001306 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001307 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001308
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001309 perq = usb_stor_buf[0];
1310 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001311
Soeren Moche4828002014-11-08 07:02:14 +01001312 /*
1313 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1314 * they would not respond to test_unit_ready .
1315 */
1316 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001317 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001318 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001319 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001320 if ((modi&0x80) == 0x80) {
1321 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001322 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001323 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001324 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1325 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1326 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001327 dev_desc->vendor[8] = 0;
1328 dev_desc->product[16] = 0;
1329 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001330#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001331 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1332 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001333#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301334 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1335 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001336 if (usb_test_unit_ready(pccb, ss)) {
1337 printf("Device NOT ready\n"
1338 " Request Sense returned %02X %02X %02X\n",
1339 pccb->sense_buf[2], pccb->sense_buf[12],
1340 pccb->sense_buf[13]);
1341 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001342 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001343 return 1;
1344 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001345 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001346 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001347 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001348 memset(pccb->pdata, 0, 8);
1349 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001350 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001351 cap[0] = 2880;
1352 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001353 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001354 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001355 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001356#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001357 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1358 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001359
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001360 cap[0] = cpu_to_be32(cap[0]);
1361 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001362#endif
1363
1364 capacity = be32_to_cpu(cap[0]) + 1;
1365 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001366
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001367 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1368 dev_desc->lba = capacity;
1369 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001370 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001371 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301372 debug(" address %d\n", dev_desc->target);
1373 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001374
1375 init_part(dev_desc);
1376
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301377 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001378 return 1;
1379}