blob: f190d8a6c40bad11a9831183e8ae0df5aa6e5661 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-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 *
wdenk149dded2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000015 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000017 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000018 *
Wolfgang Denk1a459662013-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 */
wdenk149dded2003-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.
wdenk149dded2003-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 Glass4fd074d2014-10-15 04:38:38 -060036#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060037#include <mapmem.h>
Christian Eggersc9182612008-05-21 22:12:00 +020038#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000039#include <asm/processor.h>
40
Grant Likely735dd972007-02-20 09:04:34 +010041#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000042#include <usb.h>
43
wdenk80885a92004-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 Frysinger2ff122852010-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 Saxenaf5766132012-04-03 14:56:06 +053059static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010060static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000061
wdenkaffae2b2002-08-17 09:36:01 +000062#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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ébaudeau3e8581b2012-08-10 18:27:11 +020075# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-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ébaudeaucffcc502012-08-10 18:26:50 +020095#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +000096/*
Benoît Thébaudeau4bee5c82012-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 Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000100 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200101#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200102#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200103#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200104#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000105
wdenkaffae2b2002-08-17 09:36:01 +0000106static struct us_data usb_stor[USB_MAX_STOR_DEV];
107
108
wdenk80885a92004-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 Trimarchia0cb3fc2008-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 Silbeff8fef52013-06-14 13:07:25 +0200117unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000118 lbaint_t blkcnt, void *buffer);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200119unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-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 McClintockdf3fc522011-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. Heinoaaad1082010-03-12 15:46:56 +0200127 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000128}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000129#endif
wdenkaffae2b2002-08-17 09:36:01 +0000130
Kim Phillips199adb62012-10-29 13:34:32 +0000131static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000132{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200133 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000134}
135
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100136/*******************************************************************************
Wolfgang Denk9c998aa2005-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 Vaichasf6b44e02008-03-25 12:09:07 +1100140int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200141{
142 int i;
143
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100144 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200145 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100146 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200147 dev_print(&usb_dev_desc[i]);
148 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100149 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100150 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700151
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100152 printf("No storage devices, perhaps not 'usb start'ed..?\n");
153 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200154}
155
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200156static unsigned int usb_get_max_lun(struct us_data *us)
157{
158 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530159 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-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 Saxenaf5766132012-04-03 14:56:06 +0530165 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200166 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530167 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530168 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200169}
170
Franck Julliencd749652015-03-04 21:07:00 +0100171static int usb_storage_register(struct usb_device *dev, unsigned char iface)
172{
173 int lun, max_lun, start = usb_max_devs;
174 int nb_dev = 0;
175
176 if (!usb_storage_probe(dev, iface, &usb_stor[usb_max_devs]))
177 return nb_dev;
178
179 /*
180 * OK, it's a storage device. Iterate over its LUNs
181 * and populate `usb_dev_desc'.
182 */
183 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
184 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; lun++) {
185 usb_dev_desc[usb_max_devs].lun = lun;
186 if (usb_stor_get_info(dev, &usb_stor[start],
187 &usb_dev_desc[usb_max_devs]) == 1) {
188 nb_dev++;
189 }
190 }
191
192 return nb_dev;
193}
194
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100195/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200196 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000197 * to the user if mode = 1
198 * returns current device or -1 if no
199 */
200int usb_stor_scan(int mode)
201{
Franck Julliencd749652015-03-04 21:07:00 +0100202 unsigned char i, iface;
wdenkaffae2b2002-08-17 09:36:01 +0000203 struct usb_device *dev;
204
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100205 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200206 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100207
wdenkaffae2b2002-08-17 09:36:01 +0000208 usb_disable_asynch(1); /* asynch transfer not allowed */
209
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100210 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
211 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100212 usb_dev_desc[i].if_type = IF_TYPE_USB;
213 usb_dev_desc[i].dev = i;
214 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200215 usb_dev_desc[i].target = 0xff;
216 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100217 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530218 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000219 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200220
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100221 usb_max_devs = 0;
222 for (i = 0; i < USB_MAX_DEVICE; i++) {
223 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530224 debug("i=%d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100225 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100226 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100227
Franck Julliencd749652015-03-04 21:07:00 +0100228 for (iface = 0; iface < dev->config.no_of_if; iface++) {
229 usb_max_devs += usb_storage_register(dev, iface);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200230 }
Franck Julliencd749652015-03-04 21:07:00 +0100231
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100232 /* if storage device */
233 if (usb_max_devs == USB_MAX_STOR_DEV) {
234 printf("max USB Storage Device reached: %d stopping\n",
235 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000236 break;
237 }
238 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200239
wdenkaffae2b2002-08-17 09:36:01 +0000240 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200241 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100242 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000243 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000245}
246
247static int usb_stor_irq(struct usb_device *dev)
248{
249 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100250 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000251
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100252 if (us->ip_wanted)
253 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000254 return 0;
255}
256
257
Vivek Gautamceb49722013-04-12 16:34:33 +0530258#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000259
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100260static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000261{
262 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100263 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
264 for (i = 0; i < 12; i++)
265 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000266 printf("\n");
267}
268
269static void display_int_status(unsigned long tmp)
270{
271 printf("Status: %s %s %s %s %s %s %s\n",
272 (tmp & USB_ST_ACTIVE) ? "Active" : "",
273 (tmp & USB_ST_STALLED) ? "Stalled" : "",
274 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
275 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
276 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
277 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
278 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
279}
280#endif
281/***********************************************************************
282 * Data transfer routines
283 ***********************************************************************/
284
285static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
286{
287 int max_size;
288 int this_xfer;
289 int result;
290 int partial;
291 int maxtry;
292 int stat;
293
294 /* determine the maximum packet size for these transfers */
295 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
296
297 /* while we have data left to transfer */
298 while (length) {
299
300 /* calculate how long this will be -- maximum or a remainder */
301 this_xfer = length > max_size ? max_size : length;
302 length -= this_xfer;
303
304 /* setup the retry counter */
305 maxtry = 10;
306
307 /* set up the transfer loop */
308 do {
309 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600310 debug("Bulk xfer 0x%lx(%d) try #%d\n",
311 (ulong)map_to_sysmem(buf), this_xfer,
312 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000313 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100314 this_xfer, &partial,
315 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530316 debug("bulk_msg returned %d xferred %d/%d\n",
317 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100318 if (us->pusb_dev->status != 0) {
319 /* if we stall, we need to clear it before
320 * we go on
321 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530322#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000323 display_int_status(us->pusb_dev->status);
324#endif
325 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530326 debug("stalled ->clearing endpoint" \
327 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000328 stat = us->pusb_dev->status;
329 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100330 us->pusb_dev->status = stat;
331 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530332 debug("bulk transferred" \
333 "with error %lX," \
334 " but data ok\n",
335 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000336 return 0;
337 }
338 else
339 return result;
340 }
341 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530342 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000343 return result;
344 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530345 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100346 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530347 debug(" %ld, but data ok\n",
348 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000349 return 0;
350 }
351 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530352 debug(" %ld, data %d\n",
353 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000354 if (!maxtry--)
355 return result;
356 }
357 /* update to show what data was transferred */
358 this_xfer -= partial;
359 buf += partial;
360 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100361 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000362 }
363
364 /* if we get here, we're done and successful */
365 return 0;
366}
367
wdenk149dded2003-09-10 18:20:28 +0000368static int usb_stor_BBB_reset(struct us_data *us)
369{
370 int result;
371 unsigned int pipe;
372
373 /*
374 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
375 *
376 * For Reset Recovery the host shall issue in the following order:
377 * a) a Bulk-Only Mass Storage Reset
378 * b) a Clear Feature HALT to the Bulk-In endpoint
379 * c) a Clear Feature HALT to the Bulk-Out endpoint
380 *
381 * This is done in 3 steps.
382 *
383 * If the reset doesn't succeed, the device should be port reset.
384 *
385 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
386 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530387 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100388 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
389 US_BBB_RESET,
390 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000391 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200392
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100393 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530394 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000395 return -1;
396 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200397
wdenk149dded2003-09-10 18:20:28 +0000398 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000399 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530400 debug("BBB_reset result %d: status %lX reset\n",
401 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000402 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
403 result = usb_clear_halt(us->pusb_dev, pipe);
404 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000405 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530406 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
407 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000408 /* long wait for reset */
409 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
410 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000411 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530412 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
413 result, us->pusb_dev->status);
414 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000415 return 0;
416}
417
wdenkaffae2b2002-08-17 09:36:01 +0000418/* FIXME: this reset function doesn't really reset the port, and it
419 * should. Actually it should probably do what it's doing here, and
420 * reset the port physically
421 */
422static int usb_stor_CB_reset(struct us_data *us)
423{
424 unsigned char cmd[12];
425 int result;
426
Vivek Gautamceb49722013-04-12 16:34:33 +0530427 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100428 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000429 cmd[0] = SCSI_SEND_DIAG;
430 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100431 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
432 US_CBI_ADSC,
433 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
434 0, us->ifnum, cmd, sizeof(cmd),
435 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000436
437 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000438 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530439 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
440 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000441 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
442 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
443
Vivek Gautamceb49722013-04-12 16:34:33 +0530444 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000445 return 0;
446}
447
wdenk149dded2003-09-10 18:20:28 +0000448/*
449 * Set up the command for a BBB device. Note that the actual SCSI
450 * command is copied into cbw.CBWCDB.
451 */
Kim Phillips199adb62012-10-29 13:34:32 +0000452static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000453{
454 int result;
455 int actlen;
456 int dir_in;
457 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600458 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000459
460 dir_in = US_DIRECTION(srb->cmd[0]);
461
462#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530463 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100464 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
465 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000466 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100467 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000468 printf("cmd[%d] %#x ", result, srb->cmd[result]);
469 printf("\n");
470 }
471#endif
472 /* sanity checks */
473 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530474 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000475 return -1;
476 }
477
478 /* always OUT to the ep */
479 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
480
Puneet Saxenaf5766132012-04-03 14:56:06 +0530481 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
482 cbw->dCBWTag = cpu_to_le32(CBWTag++);
483 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
484 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
485 cbw->bCBWLUN = srb->lun;
486 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000487 /* copy the command data into the CBW command data buffer */
488 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300489
Puneet Saxenaf5766132012-04-03 14:56:06 +0530490 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
491 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100492 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000493 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530494 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000495 return result;
496}
497
wdenkaffae2b2002-08-17 09:36:01 +0000498/* FIXME: we also need a CBI_command which sets up the completion
499 * interrupt, and waits for it
500 */
Kim Phillips199adb62012-10-29 13:34:32 +0000501static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000502{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200503 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100504 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000505 unsigned int pipe;
506 unsigned long status;
507
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 retry = 5;
509 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000510
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100511 if (dir_in)
512 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
513 else
514 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
515
516 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530517 debug("CBI gets a command: Try %d\n", 5 - retry);
518#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000519 usb_show_srb(srb);
520#endif
521 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100522 result = usb_control_msg(us->pusb_dev,
523 usb_sndctrlpipe(us->pusb_dev , 0),
524 US_CBI_ADSC,
525 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000526 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100527 srb->cmd, srb->cmdlen,
528 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530529 debug("CB_transport: control msg returned %d, status %lX\n",
530 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000531 /* check the return code for the command */
532 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100533 if (us->pusb_dev->status & USB_ST_STALLED) {
534 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530535 debug(" stall during command found," \
536 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100537 usb_clear_halt(us->pusb_dev,
538 usb_sndctrlpipe(us->pusb_dev, 0));
539 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000540 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530541 debug(" error during command %02X" \
542 " Stat = %lX\n", srb->cmd[0],
543 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000544 return result;
545 }
546 /* transfer the data payload for this command, if one exists*/
547
Vivek Gautamceb49722013-04-12 16:34:33 +0530548 debug("CB_transport: control msg returned %d," \
549 " direction is %s to go 0x%lx\n", result,
550 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000551 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100552 result = us_one_transfer(us, pipe, (char *)srb->pdata,
553 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530554 debug("CBI attempted to transfer data," \
555 " result is %d status %lX, len %d\n",
556 result, us->pusb_dev->status,
557 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100558 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000559 break;
560 } /* if (srb->datalen) */
561 else
562 break;
563 }
564 /* return result */
565
566 return result;
567}
568
569
Kim Phillips199adb62012-10-29 13:34:32 +0000570static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000571{
572 int timeout;
573
wdenk80885a92004-02-26 23:46:20 +0000574 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100575 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000576 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
577 timeout = 1000;
578 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300579 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000580 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000581 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000582 }
583 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100584 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000585 us->ip_wanted = 0;
586 return USB_STOR_TRANSPORT_ERROR;
587 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530588 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
589 us->ip_data, us->pusb_dev->irq_act_len,
590 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000591 /* UFI gives us ASC and ASCQ, like a request sense */
592 if (us->subclass == US_SC_UFI) {
593 if (srb->cmd[0] == SCSI_REQ_SENSE ||
594 srb->cmd[0] == SCSI_INQUIRY)
595 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000596 else if (us->ip_data)
597 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000598 else
wdenk80885a92004-02-26 23:46:20 +0000599 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000600 }
601 /* otherwise, we interpret the data normally */
602 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000603 case 0x0001:
604 return USB_STOR_TRANSPORT_GOOD;
605 case 0x0002:
606 return USB_STOR_TRANSPORT_FAILED;
607 default:
608 return USB_STOR_TRANSPORT_ERROR;
609 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000610 return USB_STOR_TRANSPORT_ERROR;
611}
612
613#define USB_TRANSPORT_UNKNOWN_RETRY 5
614#define USB_TRANSPORT_NOT_READY_RETRY 10
615
wdenk149dded2003-09-10 18:20:28 +0000616/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000617static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000618{
619 int result;
620
621 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100622 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000623 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000624 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000625 return result;
626}
627
Kim Phillips199adb62012-10-29 13:34:32 +0000628static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000629{
630 int result, retry;
631 int dir_in;
632 int actlen, data_actlen;
633 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600634 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000635#ifdef BBB_XPORT_TRACE
636 unsigned char *ptr;
637 int index;
638#endif
639
640 dir_in = US_DIRECTION(srb->cmd[0]);
641
642 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530643 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000644 result = usb_stor_BBB_comdat(srb, us);
645 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530646 debug("failed to send CBW status %ld\n",
647 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000648 usb_stor_BBB_reset(us);
649 return USB_STOR_TRANSPORT_FAILED;
650 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200651 if (!(us->flags & USB_READY))
652 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000653 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
654 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
655 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000656 data_actlen = 0;
657 /* no data, go immediately to the STATUS phase */
658 if (srb->datalen == 0)
659 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530660 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000661 if (dir_in)
662 pipe = pipein;
663 else
664 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300665
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100666 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
667 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000668 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100669 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530670 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000671 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100672 result = usb_stor_BBB_clear_endpt_stall(us,
673 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000674 if (result >= 0)
675 /* continue on to STATUS phase */
676 goto st;
677 }
678 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530679 debug("usb_bulk_msg error status %ld\n",
680 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000681 usb_stor_BBB_reset(us);
682 return USB_STOR_TRANSPORT_FAILED;
683 }
684#ifdef BBB_XPORT_TRACE
685 for (index = 0; index < data_actlen; index++)
686 printf("pdata[%d] %#x ", index, srb->pdata[index]);
687 printf("\n");
688#endif
689 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100690st:
wdenk149dded2003-09-10 18:20:28 +0000691 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100692again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530693 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530694 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200695 &actlen, USB_CNTL_TIMEOUT*5);
696
wdenk149dded2003-09-10 18:20:28 +0000697 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100698 if ((result < 0) && (retry < 1) &&
699 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530700 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000701 /* clear the STALL on the endpoint */
702 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
703 if (result >= 0 && (retry++ < 1))
704 /* do a retry */
705 goto again;
706 }
707 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530708 debug("usb_bulk_msg error status %ld\n",
709 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000710 usb_stor_BBB_reset(us);
711 return USB_STOR_TRANSPORT_FAILED;
712 }
713#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530714 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000715 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
716 printf("ptr[%d] %#x ", index, ptr[index]);
717 printf("\n");
718#endif
719 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530720 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000721 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
722 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530723 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530724 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530727 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530728 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000729 usb_stor_BBB_reset(us);
730 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530731 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530732 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000733 usb_stor_BBB_reset(us);
734 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530735 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530736 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000737 usb_stor_BBB_reset(us);
738 return USB_STOR_TRANSPORT_FAILED;
739 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530740 debug("transferred %dB instead of %ldB\n",
741 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000742 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530743 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530744 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000745 return USB_STOR_TRANSPORT_FAILED;
746 }
747
748 return result;
749}
750
Kim Phillips199adb62012-10-29 13:34:32 +0000751static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000752{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100753 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000754 ccb *psrb;
755 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100756 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000757
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200758 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100759 status = USB_STOR_TRANSPORT_GOOD;
760 retry = 0;
761 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000762 /* issue the command */
763do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100764 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530765 debug("command / Data returned %d, status %lX\n",
766 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000767 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100768 if (us->protocol == US_PR_CBI) {
769 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000770 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100771 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530772 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000773 return status;
774 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100775 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
776 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
777 if (!us->ip_data) {
778 /* if the status is good, report it */
779 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530780 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000781 return status;
782 }
783 }
784 }
785 /* do we have to issue an auto request? */
786 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100787 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530788 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000789 us->transport_reset(us);
790 return USB_STOR_TRANSPORT_ERROR;
791 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100792 if ((us->protocol == US_PR_CBI) &&
793 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
794 (srb->cmd[0] == SCSI_INQUIRY))) {
795 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530796 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000797 return USB_STOR_TRANSPORT_GOOD;
798 }
799 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100800 memset(&psrb->cmd[0], 0, 12);
801 psrb->cmd[0] = SCSI_REQ_SENSE;
802 psrb->cmd[1] = srb->lun << 5;
803 psrb->cmd[4] = 18;
804 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200805 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000807 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100808 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530809 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000810 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100811 if (us->protocol == US_PR_CBI)
812 status = usb_stor_CBI_get_status(psrb, us);
813
814 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530815 debug(" AUTO REQUEST ERROR %ld\n",
816 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000817 return USB_STOR_TRANSPORT_ERROR;
818 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530819 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
820 srb->sense_buf[0], srb->sense_buf[2],
821 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000822 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100823 if ((srb->sense_buf[2] == 0) &&
824 (srb->sense_buf[12] == 0) &&
825 (srb->sense_buf[13] == 0)) {
826 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000827 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100828 }
829
wdenkaffae2b2002-08-17 09:36:01 +0000830 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100831 switch (srb->sense_buf[2]) {
832 case 0x01:
833 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000834 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000835 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100836 case 0x02:
837 /* Not Ready */
838 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
839 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
840 " 0x%02X (NOT READY)\n", srb->cmd[0],
841 srb->sense_buf[0], srb->sense_buf[2],
842 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000843 return USB_STOR_TRANSPORT_FAILED;
844 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000845 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000846 goto do_retry;
847 }
848 break;
849 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
851 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
852 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
853 srb->sense_buf[2], srb->sense_buf[12],
854 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000855 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100856 } else
wdenk149dded2003-09-10 18:20:28 +0000857 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000858 break;
wdenkaffae2b2002-08-17 09:36:01 +0000859 }
860 return USB_STOR_TRANSPORT_FAILED;
861}
862
863
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100864static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000865{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 int retry, i;
867 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000868 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100869 memset(&srb->cmd[0], 0, 12);
870 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200871 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100872 srb->cmd[4] = 36;
873 srb->datalen = 36;
874 srb->cmdlen = 12;
875 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530876 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100877 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000878 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200879 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000880
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100881 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000882 printf("error in inquiry\n");
883 return -1;
884 }
885 return 0;
886}
887
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100888static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000889{
890 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000891
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100892 ptr = (char *)srb->pdata;
893 memset(&srb->cmd[0], 0, 12);
894 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200895 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100896 srb->cmd[4] = 18;
897 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200898 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100899 srb->cmdlen = 12;
900 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530901 debug("Request Sense returned %02X %02X %02X\n",
902 srb->sense_buf[2], srb->sense_buf[12],
903 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100904 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000905 return 0;
906}
907
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000909{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200910 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000911
wdenkaffae2b2002-08-17 09:36:01 +0000912 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100913 memset(&srb->cmd[0], 0, 12);
914 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200915 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100916 srb->datalen = 0;
917 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200918 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
919 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000920 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200921 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100922 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800923 /*
924 * Check the Key Code Qualifier, if it matches
925 * "Not Ready - medium not present"
926 * (the sense Key equals 0x2 and the ASC is 0x3a)
927 * return immediately as the medium being absent won't change
928 * unless there is a user action.
929 */
930 if ((srb->sense_buf[2] == 0x02) &&
931 (srb->sense_buf[12] == 0x3a))
932 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000933 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100934 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000935
wdenkaffae2b2002-08-17 09:36:01 +0000936 return -1;
937}
938
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100939static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000940{
941 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100942 /* XXX retries */
943 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000944 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100945 memset(&srb->cmd[0], 0, 12);
946 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200947 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100948 srb->datalen = 8;
949 srb->cmdlen = 12;
950 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000951 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100952 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000953
wdenkaffae2b2002-08-17 09:36:01 +0000954 return -1;
955}
956
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100957static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
958 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000959{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100960 memset(&srb->cmd[0], 0, 12);
961 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200962 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100963 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
964 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
965 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
966 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
967 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
968 srb->cmd[8] = (unsigned char) blocks & 0xff;
969 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530970 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100971 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000972}
973
Mahavir Jain127e1082009-11-03 12:22:10 +0530974static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
975 unsigned short blocks)
976{
977 memset(&srb->cmd[0], 0, 12);
978 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200979 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +0530980 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
981 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
982 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
983 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
984 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
985 srb->cmd[8] = (unsigned char) blocks & 0xff;
986 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530987 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +0530988 return ss->transport(srb, ss);
989}
990
wdenkaffae2b2002-08-17 09:36:01 +0000991
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +0200992#ifdef CONFIG_USB_BIN_FIXUP
993/*
994 * Some USB storage devices queried for SCSI identification data respond with
995 * binary strings, which if output to the console freeze the terminal. The
996 * workaround is to modify the vendor and product strings read from such
997 * device with proper values (as reported by 'usb info').
998 *
999 * Vendor and product length limits are taken from the definition of
1000 * block_dev_desc_t in include/part.h.
1001 */
1002static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1003 unsigned char vendor[],
1004 unsigned char product[]) {
1005 const unsigned char max_vendor_len = 40;
1006 const unsigned char max_product_len = 20;
1007 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001008 strncpy((char *)vendor, "SMSC", max_vendor_len);
1009 strncpy((char *)product, "Flash Media Cntrller",
1010 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001011 }
1012}
1013#endif /* CONFIG_USB_BIN_FIXUP */
1014
Sascha Silbeff8fef52013-06-14 13:07:25 +02001015unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001016 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001017{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001018 lbaint_t start, blks;
1019 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001020 unsigned short smallblks;
1021 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001022 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001023 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001024 ccb *srb = &usb_ccb;
1025
1026 if (blkcnt == 0)
1027 return 0;
1028
1029 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001030 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001031 debug("\nusb_read: dev %d\n", device);
1032 dev = usb_dev_desc[device].priv;
1033 if (!dev) {
1034 debug("%s: No device\n", __func__);
1035 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001036 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001037 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001038
1039 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001040 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001041 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001042 start = blknr;
1043 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044
Vivek Gautamceb49722013-04-12 16:34:33 +05301045 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001046 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001047
wdenkaffae2b2002-08-17 09:36:01 +00001048 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001049 /* XXX need some comment here */
1050 retry = 2;
1051 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001052 if (blks > USB_MAX_XFER_BLK)
1053 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001054 else
1055 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001056retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001057 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001058 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001059 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1060 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001061 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301062 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001063 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001065 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001066 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001067 break;
1068 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 start += smallblks;
1070 blks -= smallblks;
1071 buf_addr += srb->datalen;
1072 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001073 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001074
Vivek Gautamceb49722013-04-12 16:34:33 +05301075 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001076 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301077 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001078
wdenkaffae2b2002-08-17 09:36:01 +00001079 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001080 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001081 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001082 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001083}
1084
Sascha Silbeff8fef52013-06-14 13:07:25 +02001085unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001086 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301087{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001088 lbaint_t start, blks;
1089 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301090 unsigned short smallblks;
1091 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001092 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001093 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301094 ccb *srb = &usb_ccb;
1095
1096 if (blkcnt == 0)
1097 return 0;
1098
1099 device &= 0xff;
1100 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001101 debug("\nusb_write: dev %d\n", device);
1102 dev = usb_dev_desc[device].priv;
1103 if (!dev)
1104 return 0;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001105 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301106
1107 usb_disable_asynch(1); /* asynch transfer not allowed */
1108
1109 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001110 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301111 start = blknr;
1112 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301113
Vivek Gautamceb49722013-04-12 16:34:33 +05301114 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001115 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301116
1117 do {
1118 /* If write fails retry for max retry count else
1119 * return with number of blocks written successfully.
1120 */
1121 retry = 2;
1122 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001123 if (blks > USB_MAX_XFER_BLK)
1124 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301125 else
1126 smallblks = (unsigned short) blks;
1127retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001128 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301129 usb_show_progress();
1130 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1131 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001132 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301133 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001134 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301135 if (retry--)
1136 goto retry_it;
1137 blkcnt -= blks;
1138 break;
1139 }
1140 start += smallblks;
1141 blks -= smallblks;
1142 buf_addr += srb->datalen;
1143 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001144 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301145
Simon Glass4fd074d2014-10-15 04:38:38 -06001146 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1147 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301148
1149 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001150 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001151 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301152 return blkcnt;
1153
1154}
wdenkaffae2b2002-08-17 09:36:01 +00001155
1156/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001157int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1158 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001159{
Tom Rix8f8bd562009-10-31 12:37:38 -05001160 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001161 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301162 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001163 unsigned int flags = 0;
1164
1165 int protocol = 0;
1166 int subclass = 0;
1167
wdenkaffae2b2002-08-17 09:36:01 +00001168 /* let's examine the device now */
1169 iface = &dev->config.if_desc[ifnum];
1170
1171#if 0
1172 /* this is the place to patch some storage devices */
Vivek Gautamceb49722013-04-12 16:34:33 +05301173 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001174 dev->descriptor.idProduct);
1175
1176 if ((dev->descriptor.idVendor) == 0x066b &&
1177 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301178 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001179 protocol = US_PR_CB;
1180 subclass = US_SC_UFI; /* an assumption */
1181 }
1182#endif
1183
1184 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001185 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1186 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1187 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001188 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001189 /* if it's not a mass storage, we go no further */
1190 return 0;
1191 }
1192
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001193 memset(ss, 0, sizeof(struct us_data));
1194
wdenkaffae2b2002-08-17 09:36:01 +00001195 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301196 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001197
1198 /* Initialize the us_data structure with some useful info */
1199 ss->flags = flags;
1200 ss->ifnum = ifnum;
1201 ss->pusb_dev = dev;
1202 ss->attention_done = 0;
1203
1204 /* If the device has subclass and protocol, then use that. Otherwise,
1205 * take data from the specific interface.
1206 */
1207 if (subclass) {
1208 ss->subclass = subclass;
1209 ss->protocol = protocol;
1210 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001211 ss->subclass = iface->desc.bInterfaceSubClass;
1212 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001213 }
1214
1215 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301216 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001217 switch (ss->protocol) {
1218 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301219 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001220 ss->transport = usb_stor_CB_transport;
1221 ss->transport_reset = usb_stor_CB_reset;
1222 break;
1223
1224 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301225 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001226 ss->transport = usb_stor_CB_transport;
1227 ss->transport_reset = usb_stor_CB_reset;
1228 break;
wdenk149dded2003-09-10 18:20:28 +00001229 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301230 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001231 ss->transport = usb_stor_BBB_transport;
1232 ss->transport_reset = usb_stor_BBB_reset;
1233 break;
wdenkaffae2b2002-08-17 09:36:01 +00001234 default:
wdenk80885a92004-02-26 23:46:20 +00001235 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001236 return 0;
1237 break;
1238 }
1239
1240 /*
1241 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1242 * An optional interrupt is OK (necessary for CBI protocol).
1243 * We will ignore any others.
1244 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001245 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301246 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001247 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301248 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001249 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301250 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1251 ss->ep_in = ep_desc->bEndpointAddress &
1252 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001253 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001254 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301255 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001256 USB_ENDPOINT_NUMBER_MASK;
1257 }
1258
1259 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301260 if ((ep_desc->bmAttributes &
1261 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1262 ss->ep_int = ep_desc->bEndpointAddress &
1263 USB_ENDPOINT_NUMBER_MASK;
1264 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001265 }
1266 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301267 debug("Endpoints In %d Out %d Int %d\n",
1268 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001269
1270 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001271 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001272 !ss->ep_in || !ss->ep_out ||
1273 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301274 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001275 return 0;
1276 }
1277 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001278 /* We only handle certain protocols. Currently, these are
1279 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001280 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001281 */
wdenk80885a92004-02-26 23:46:20 +00001282 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1283 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001284 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001285 return 0;
1286 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001287 if (ss->ep_int) {
1288 /* we had found an interrupt endpoint, prepare irq pipe
1289 * set up the IRQ pipe and handler
1290 */
wdenkaffae2b2002-08-17 09:36:01 +00001291 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1292 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1293 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001294 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001295 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001296 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001297 return 1;
1298}
1299
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001300int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1301 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001302{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001303 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001304 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1305 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1306 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001307 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001308
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001309 pccb->pdata = usb_stor_buf;
1310
1311 dev_desc->target = dev->devnum;
1312 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301313 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001314
Simon Glass1d5827a2015-03-25 12:22:12 -06001315 if (usb_inquiry(pccb, ss)) {
1316 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001317 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001318 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001319
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001320 perq = usb_stor_buf[0];
1321 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001322
Soeren Moch6a559bb2014-11-08 07:02:14 +01001323 /*
1324 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1325 * they would not respond to test_unit_ready .
1326 */
1327 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001328 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001329 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001330 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001331 if ((modi&0x80) == 0x80) {
1332 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001333 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001334 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001335 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1336 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1337 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001338 dev_desc->vendor[8] = 0;
1339 dev_desc->product[16] = 0;
1340 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001341#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001342 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1343 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001344#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301345 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1346 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001347 if (usb_test_unit_ready(pccb, ss)) {
1348 printf("Device NOT ready\n"
1349 " Request Sense returned %02X %02X %02X\n",
1350 pccb->sense_buf[2], pccb->sense_buf[12],
1351 pccb->sense_buf[13]);
1352 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001353 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001354 return 1;
1355 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001356 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001357 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001358 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001359 memset(pccb->pdata, 0, 8);
1360 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001361 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001362 cap[0] = 2880;
1363 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001364 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001365 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001366 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001367#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001368 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1369 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001370
Christian Eggersc9182612008-05-21 22:12:00 +02001371 cap[0] = cpu_to_be32(cap[0]);
1372 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001373#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001374
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001375 capacity = be32_to_cpu(cap[0]) + 1;
1376 blksz = be32_to_cpu(cap[1]);
1377
1378 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1379 dev_desc->lba = capacity;
1380 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001381 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001382 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301383 debug(" address %d\n", dev_desc->target);
1384 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001385
1386 init_part(dev_desc);
1387
Vivek Gautamceb49722013-04-12 16:34:33 +05301388 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001389 return 1;
1390}