blob: 62527a98a0cac9bf4913614c0fb390bebc41bb8f [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>
Christian Eggersc9182612008-05-21 22:12:00 +020037#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000038#include <asm/processor.h>
39
Grant Likely735dd972007-02-20 09:04:34 +010040#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000041#include <usb.h>
42
wdenk80885a92004-02-26 23:46:20 +000043#undef BBB_COMDAT_TRACE
44#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000045
wdenkaffae2b2002-08-17 09:36:01 +000046#include <scsi.h>
47/* direction table -- this indicates the direction of the data
48 * transfer for each command code -- a 1 indicates input
49 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040050static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000051 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
52 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
55};
56#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
57
Puneet Saxenaf5766132012-04-03 14:56:06 +053058static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010059static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000060
wdenkaffae2b2002-08-17 09:36:01 +000061#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010062static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000063
64static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
65
66struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010067typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
68typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000069
70struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010071 struct usb_device *pusb_dev; /* this usb_device */
72
73 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020074# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010075 unsigned char ifnum; /* interface number */
76 unsigned char ep_in; /* in endpoint */
77 unsigned char ep_out; /* out ....... */
78 unsigned char ep_int; /* interrupt . */
79 unsigned char subclass; /* as in overview */
80 unsigned char protocol; /* .............. */
81 unsigned char attention_done; /* force attn on first cmd */
82 unsigned short ip_data; /* interrupt data */
83 int action; /* what to do */
84 int ip_wanted; /* needed */
85 int *irq_handle; /* for USB int requests */
86 unsigned int irqpipe; /* pipe for release_irq */
87 unsigned char irqmaxp; /* max packed for irq Pipe */
88 unsigned char irqinterval; /* Intervall for IRQ Pipe */
89 ccb *srb; /* current srb */
90 trans_reset transport_reset; /* reset routine */
91 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000092};
93
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +020094#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +000095/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +020096 * The U-Boot EHCI driver can handle any transfer length as long as there is
97 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
98 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +000099 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200100#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200101#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200102#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200103#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000104
wdenkaffae2b2002-08-17 09:36:01 +0000105static struct us_data usb_stor[USB_MAX_STOR_DEV];
106
107
wdenk80885a92004-02-26 23:46:20 +0000108#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000109#define USB_STOR_TRANSPORT_FAILED -1
110#define USB_STOR_TRANSPORT_ERROR -2
111
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100112int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
113 block_dev_desc_t *dev_desc);
114int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
115 struct us_data *ss);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200116unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000117 lbaint_t blkcnt, void *buffer);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200118unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000119 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000120struct usb_device * usb_get_dev_index(int index);
121void uhci_show_temp_int_td(void);
122
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000123#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000124block_dev_desc_t *usb_stor_get_dev(int index)
125{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200126 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000127}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000128#endif
wdenkaffae2b2002-08-17 09:36:01 +0000129
Kim Phillips199adb62012-10-29 13:34:32 +0000130static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000131{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200132 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000133}
134
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100135/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200136 * show info on storage devices; 'usb start/init' must be invoked earlier
137 * as we only retrieve structures populated during devices initialization
138 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100139int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200140{
141 int i;
142
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100143 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200144 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100145 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200146 dev_print(&usb_dev_desc[i]);
147 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100148 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100149 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700150
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100151 printf("No storage devices, perhaps not 'usb start'ed..?\n");
152 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200153}
154
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200155static unsigned int usb_get_max_lun(struct us_data *us)
156{
157 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530158 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200159 len = usb_control_msg(us->pusb_dev,
160 usb_rcvctrlpipe(us->pusb_dev, 0),
161 US_BBB_GET_MAX_LUN,
162 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
163 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530164 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200165 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530166 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530167 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200168}
169
Franck Julliencd749652015-03-04 21:07:00 +0100170static int usb_storage_register(struct usb_device *dev, unsigned char iface)
171{
172 int lun, max_lun, start = usb_max_devs;
173 int nb_dev = 0;
174
175 if (!usb_storage_probe(dev, iface, &usb_stor[usb_max_devs]))
176 return nb_dev;
177
178 /*
179 * OK, it's a storage device. Iterate over its LUNs
180 * and populate `usb_dev_desc'.
181 */
182 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
183 for (lun = 0; lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; lun++) {
184 usb_dev_desc[usb_max_devs].lun = lun;
185 if (usb_stor_get_info(dev, &usb_stor[start],
186 &usb_dev_desc[usb_max_devs]) == 1) {
187 nb_dev++;
188 }
189 }
190
191 return nb_dev;
192}
193
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100194/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200195 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000196 * to the user if mode = 1
197 * returns current device or -1 if no
198 */
199int usb_stor_scan(int mode)
200{
Franck Julliencd749652015-03-04 21:07:00 +0100201 unsigned char i, iface;
wdenkaffae2b2002-08-17 09:36:01 +0000202 struct usb_device *dev;
203
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100204 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200205 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100206
wdenkaffae2b2002-08-17 09:36:01 +0000207 usb_disable_asynch(1); /* asynch transfer not allowed */
208
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100209 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
210 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100211 usb_dev_desc[i].if_type = IF_TYPE_USB;
212 usb_dev_desc[i].dev = i;
213 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200214 usb_dev_desc[i].target = 0xff;
215 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100216 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530217 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000218 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200219
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100220 usb_max_devs = 0;
221 for (i = 0; i < USB_MAX_DEVICE; i++) {
222 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530223 debug("i=%d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100224 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100225 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100226
Franck Julliencd749652015-03-04 21:07:00 +0100227 for (iface = 0; iface < dev->config.no_of_if; iface++) {
228 usb_max_devs += usb_storage_register(dev, iface);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200229 }
Franck Julliencd749652015-03-04 21:07:00 +0100230
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100231 /* if storage device */
232 if (usb_max_devs == USB_MAX_STOR_DEV) {
233 printf("max USB Storage Device reached: %d stopping\n",
234 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000235 break;
236 }
237 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200238
wdenkaffae2b2002-08-17 09:36:01 +0000239 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200240 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100241 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000242 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100243 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000244}
245
246static int usb_stor_irq(struct usb_device *dev)
247{
248 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100249 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000250
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100251 if (us->ip_wanted)
252 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000253 return 0;
254}
255
256
Vivek Gautamceb49722013-04-12 16:34:33 +0530257#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000258
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100259static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000260{
261 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100262 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
263 for (i = 0; i < 12; i++)
264 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000265 printf("\n");
266}
267
268static void display_int_status(unsigned long tmp)
269{
270 printf("Status: %s %s %s %s %s %s %s\n",
271 (tmp & USB_ST_ACTIVE) ? "Active" : "",
272 (tmp & USB_ST_STALLED) ? "Stalled" : "",
273 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
274 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
275 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
276 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
277 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
278}
279#endif
280/***********************************************************************
281 * Data transfer routines
282 ***********************************************************************/
283
284static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
285{
286 int max_size;
287 int this_xfer;
288 int result;
289 int partial;
290 int maxtry;
291 int stat;
292
293 /* determine the maximum packet size for these transfers */
294 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
295
296 /* while we have data left to transfer */
297 while (length) {
298
299 /* calculate how long this will be -- maximum or a remainder */
300 this_xfer = length > max_size ? max_size : length;
301 length -= this_xfer;
302
303 /* setup the retry counter */
304 maxtry = 10;
305
306 /* set up the transfer loop */
307 do {
308 /* transfer the data */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300309 debug("Bulk xfer %p(%d) try #%d\n",
310 buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000311 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100312 this_xfer, &partial,
313 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530314 debug("bulk_msg returned %d xferred %d/%d\n",
315 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100316 if (us->pusb_dev->status != 0) {
317 /* if we stall, we need to clear it before
318 * we go on
319 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530320#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000321 display_int_status(us->pusb_dev->status);
322#endif
323 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530324 debug("stalled ->clearing endpoint" \
325 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000326 stat = us->pusb_dev->status;
327 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100328 us->pusb_dev->status = stat;
329 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530330 debug("bulk transferred" \
331 "with error %lX," \
332 " but data ok\n",
333 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000334 return 0;
335 }
336 else
337 return result;
338 }
339 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530340 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000341 return result;
342 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530343 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100344 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530345 debug(" %ld, but data ok\n",
346 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000347 return 0;
348 }
349 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530350 debug(" %ld, data %d\n",
351 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000352 if (!maxtry--)
353 return result;
354 }
355 /* update to show what data was transferred */
356 this_xfer -= partial;
357 buf += partial;
358 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100359 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000360 }
361
362 /* if we get here, we're done and successful */
363 return 0;
364}
365
wdenk149dded2003-09-10 18:20:28 +0000366static int usb_stor_BBB_reset(struct us_data *us)
367{
368 int result;
369 unsigned int pipe;
370
371 /*
372 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
373 *
374 * For Reset Recovery the host shall issue in the following order:
375 * a) a Bulk-Only Mass Storage Reset
376 * b) a Clear Feature HALT to the Bulk-In endpoint
377 * c) a Clear Feature HALT to the Bulk-Out endpoint
378 *
379 * This is done in 3 steps.
380 *
381 * If the reset doesn't succeed, the device should be port reset.
382 *
383 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
384 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530385 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100386 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
387 US_BBB_RESET,
388 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000389 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200390
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100391 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530392 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000393 return -1;
394 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200395
wdenk149dded2003-09-10 18:20:28 +0000396 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000397 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530398 debug("BBB_reset result %d: status %lX reset\n",
399 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000400 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
401 result = usb_clear_halt(us->pusb_dev, pipe);
402 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000403 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530404 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
405 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000406 /* long wait for reset */
407 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
408 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000409 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530410 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
411 result, us->pusb_dev->status);
412 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000413 return 0;
414}
415
wdenkaffae2b2002-08-17 09:36:01 +0000416/* FIXME: this reset function doesn't really reset the port, and it
417 * should. Actually it should probably do what it's doing here, and
418 * reset the port physically
419 */
420static int usb_stor_CB_reset(struct us_data *us)
421{
422 unsigned char cmd[12];
423 int result;
424
Vivek Gautamceb49722013-04-12 16:34:33 +0530425 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100426 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000427 cmd[0] = SCSI_SEND_DIAG;
428 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100429 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
430 US_CBI_ADSC,
431 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
432 0, us->ifnum, cmd, sizeof(cmd),
433 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000434
435 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000436 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530437 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
438 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000439 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
440 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
441
Vivek Gautamceb49722013-04-12 16:34:33 +0530442 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000443 return 0;
444}
445
wdenk149dded2003-09-10 18:20:28 +0000446/*
447 * Set up the command for a BBB device. Note that the actual SCSI
448 * command is copied into cbw.CBWCDB.
449 */
Kim Phillips199adb62012-10-29 13:34:32 +0000450static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000451{
452 int result;
453 int actlen;
454 int dir_in;
455 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600456 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000457
458 dir_in = US_DIRECTION(srb->cmd[0]);
459
460#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530461 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100462 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
463 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000464 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100465 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000466 printf("cmd[%d] %#x ", result, srb->cmd[result]);
467 printf("\n");
468 }
469#endif
470 /* sanity checks */
471 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530472 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000473 return -1;
474 }
475
476 /* always OUT to the ep */
477 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
478
Puneet Saxenaf5766132012-04-03 14:56:06 +0530479 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
480 cbw->dCBWTag = cpu_to_le32(CBWTag++);
481 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
482 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
483 cbw->bCBWLUN = srb->lun;
484 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000485 /* copy the command data into the CBW command data buffer */
486 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300487
Puneet Saxenaf5766132012-04-03 14:56:06 +0530488 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
489 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100490 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000491 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530492 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000493 return result;
494}
495
wdenkaffae2b2002-08-17 09:36:01 +0000496/* FIXME: we also need a CBI_command which sets up the completion
497 * interrupt, and waits for it
498 */
Kim Phillips199adb62012-10-29 13:34:32 +0000499static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000500{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200501 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100502 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000503 unsigned int pipe;
504 unsigned long status;
505
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100506 retry = 5;
507 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000508
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100509 if (dir_in)
510 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
511 else
512 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
513
514 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530515 debug("CBI gets a command: Try %d\n", 5 - retry);
516#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000517 usb_show_srb(srb);
518#endif
519 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100520 result = usb_control_msg(us->pusb_dev,
521 usb_sndctrlpipe(us->pusb_dev , 0),
522 US_CBI_ADSC,
523 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000524 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100525 srb->cmd, srb->cmdlen,
526 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530527 debug("CB_transport: control msg returned %d, status %lX\n",
528 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000529 /* check the return code for the command */
530 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100531 if (us->pusb_dev->status & USB_ST_STALLED) {
532 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530533 debug(" stall during command found," \
534 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100535 usb_clear_halt(us->pusb_dev,
536 usb_sndctrlpipe(us->pusb_dev, 0));
537 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000538 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530539 debug(" error during command %02X" \
540 " Stat = %lX\n", srb->cmd[0],
541 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000542 return result;
543 }
544 /* transfer the data payload for this command, if one exists*/
545
Vivek Gautamceb49722013-04-12 16:34:33 +0530546 debug("CB_transport: control msg returned %d," \
547 " direction is %s to go 0x%lx\n", result,
548 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000549 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100550 result = us_one_transfer(us, pipe, (char *)srb->pdata,
551 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530552 debug("CBI attempted to transfer data," \
553 " result is %d status %lX, len %d\n",
554 result, us->pusb_dev->status,
555 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100556 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000557 break;
558 } /* if (srb->datalen) */
559 else
560 break;
561 }
562 /* return result */
563
564 return result;
565}
566
567
Kim Phillips199adb62012-10-29 13:34:32 +0000568static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000569{
570 int timeout;
571
wdenk80885a92004-02-26 23:46:20 +0000572 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100573 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000574 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
575 timeout = 1000;
576 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300577 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000578 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000579 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000580 }
581 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100582 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000583 us->ip_wanted = 0;
584 return USB_STOR_TRANSPORT_ERROR;
585 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530586 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
587 us->ip_data, us->pusb_dev->irq_act_len,
588 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000589 /* UFI gives us ASC and ASCQ, like a request sense */
590 if (us->subclass == US_SC_UFI) {
591 if (srb->cmd[0] == SCSI_REQ_SENSE ||
592 srb->cmd[0] == SCSI_INQUIRY)
593 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000594 else if (us->ip_data)
595 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000596 else
wdenk80885a92004-02-26 23:46:20 +0000597 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000598 }
599 /* otherwise, we interpret the data normally */
600 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000601 case 0x0001:
602 return USB_STOR_TRANSPORT_GOOD;
603 case 0x0002:
604 return USB_STOR_TRANSPORT_FAILED;
605 default:
606 return USB_STOR_TRANSPORT_ERROR;
607 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000608 return USB_STOR_TRANSPORT_ERROR;
609}
610
611#define USB_TRANSPORT_UNKNOWN_RETRY 5
612#define USB_TRANSPORT_NOT_READY_RETRY 10
613
wdenk149dded2003-09-10 18:20:28 +0000614/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000615static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000616{
617 int result;
618
619 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100620 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000621 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000622 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000623 return result;
624}
625
Kim Phillips199adb62012-10-29 13:34:32 +0000626static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000627{
628 int result, retry;
629 int dir_in;
630 int actlen, data_actlen;
631 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600632 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000633#ifdef BBB_XPORT_TRACE
634 unsigned char *ptr;
635 int index;
636#endif
637
638 dir_in = US_DIRECTION(srb->cmd[0]);
639
640 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530641 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000642 result = usb_stor_BBB_comdat(srb, us);
643 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530644 debug("failed to send CBW status %ld\n",
645 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000646 usb_stor_BBB_reset(us);
647 return USB_STOR_TRANSPORT_FAILED;
648 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200649 if (!(us->flags & USB_READY))
650 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000651 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
652 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
653 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000654 data_actlen = 0;
655 /* no data, go immediately to the STATUS phase */
656 if (srb->datalen == 0)
657 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530658 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000659 if (dir_in)
660 pipe = pipein;
661 else
662 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300663
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
665 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000666 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100667 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530668 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000669 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100670 result = usb_stor_BBB_clear_endpt_stall(us,
671 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000672 if (result >= 0)
673 /* continue on to STATUS phase */
674 goto st;
675 }
676 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530677 debug("usb_bulk_msg error status %ld\n",
678 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000679 usb_stor_BBB_reset(us);
680 return USB_STOR_TRANSPORT_FAILED;
681 }
682#ifdef BBB_XPORT_TRACE
683 for (index = 0; index < data_actlen; index++)
684 printf("pdata[%d] %#x ", index, srb->pdata[index]);
685 printf("\n");
686#endif
687 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100688st:
wdenk149dded2003-09-10 18:20:28 +0000689 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100690again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530691 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530692 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200693 &actlen, USB_CNTL_TIMEOUT*5);
694
wdenk149dded2003-09-10 18:20:28 +0000695 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100696 if ((result < 0) && (retry < 1) &&
697 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530698 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000699 /* clear the STALL on the endpoint */
700 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
701 if (result >= 0 && (retry++ < 1))
702 /* do a retry */
703 goto again;
704 }
705 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530706 debug("usb_bulk_msg error status %ld\n",
707 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000708 usb_stor_BBB_reset(us);
709 return USB_STOR_TRANSPORT_FAILED;
710 }
711#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530712 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000713 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
714 printf("ptr[%d] %#x ", index, ptr[index]);
715 printf("\n");
716#endif
717 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530718 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000719 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
720 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530721 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530722 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000723 usb_stor_BBB_reset(us);
724 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530725 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530726 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000727 usb_stor_BBB_reset(us);
728 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530729 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530730 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000731 usb_stor_BBB_reset(us);
732 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530733 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530734 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000735 usb_stor_BBB_reset(us);
736 return USB_STOR_TRANSPORT_FAILED;
737 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530738 debug("transferred %dB instead of %ldB\n",
739 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000740 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530741 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530742 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000743 return USB_STOR_TRANSPORT_FAILED;
744 }
745
746 return result;
747}
748
Kim Phillips199adb62012-10-29 13:34:32 +0000749static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000750{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100751 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000752 ccb *psrb;
753 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100754 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000755
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200756 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100757 status = USB_STOR_TRANSPORT_GOOD;
758 retry = 0;
759 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000760 /* issue the command */
761do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100762 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530763 debug("command / Data returned %d, status %lX\n",
764 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000765 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100766 if (us->protocol == US_PR_CBI) {
767 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000768 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100769 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530770 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000771 return status;
772 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100773 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
774 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
775 if (!us->ip_data) {
776 /* if the status is good, report it */
777 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530778 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000779 return status;
780 }
781 }
782 }
783 /* do we have to issue an auto request? */
784 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100785 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530786 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000787 us->transport_reset(us);
788 return USB_STOR_TRANSPORT_ERROR;
789 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100790 if ((us->protocol == US_PR_CBI) &&
791 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
792 (srb->cmd[0] == SCSI_INQUIRY))) {
793 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530794 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000795 return USB_STOR_TRANSPORT_GOOD;
796 }
797 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100798 memset(&psrb->cmd[0], 0, 12);
799 psrb->cmd[0] = SCSI_REQ_SENSE;
800 psrb->cmd[1] = srb->lun << 5;
801 psrb->cmd[4] = 18;
802 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200803 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100804 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000805 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530807 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000808 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100809 if (us->protocol == US_PR_CBI)
810 status = usb_stor_CBI_get_status(psrb, us);
811
812 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530813 debug(" AUTO REQUEST ERROR %ld\n",
814 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000815 return USB_STOR_TRANSPORT_ERROR;
816 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530817 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
818 srb->sense_buf[0], srb->sense_buf[2],
819 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000820 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100821 if ((srb->sense_buf[2] == 0) &&
822 (srb->sense_buf[12] == 0) &&
823 (srb->sense_buf[13] == 0)) {
824 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000825 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100826 }
827
wdenkaffae2b2002-08-17 09:36:01 +0000828 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100829 switch (srb->sense_buf[2]) {
830 case 0x01:
831 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000832 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000833 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100834 case 0x02:
835 /* Not Ready */
836 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
837 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
838 " 0x%02X (NOT READY)\n", srb->cmd[0],
839 srb->sense_buf[0], srb->sense_buf[2],
840 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000841 return USB_STOR_TRANSPORT_FAILED;
842 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000843 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000844 goto do_retry;
845 }
846 break;
847 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
849 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
850 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
851 srb->sense_buf[2], srb->sense_buf[12],
852 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000853 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100854 } else
wdenk149dded2003-09-10 18:20:28 +0000855 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000856 break;
wdenkaffae2b2002-08-17 09:36:01 +0000857 }
858 return USB_STOR_TRANSPORT_FAILED;
859}
860
861
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100862static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000863{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100864 int retry, i;
865 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000866 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100867 memset(&srb->cmd[0], 0, 12);
868 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200869 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 srb->cmd[4] = 36;
871 srb->datalen = 36;
872 srb->cmdlen = 12;
873 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530874 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100875 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000876 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200877 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000878
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100879 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000880 printf("error in inquiry\n");
881 return -1;
882 }
883 return 0;
884}
885
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100886static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000887{
888 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000889
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100890 ptr = (char *)srb->pdata;
891 memset(&srb->cmd[0], 0, 12);
892 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200893 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100894 srb->cmd[4] = 18;
895 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200896 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100897 srb->cmdlen = 12;
898 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530899 debug("Request Sense returned %02X %02X %02X\n",
900 srb->sense_buf[2], srb->sense_buf[12],
901 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100902 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000903 return 0;
904}
905
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000907{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200908 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000909
wdenkaffae2b2002-08-17 09:36:01 +0000910 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911 memset(&srb->cmd[0], 0, 12);
912 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200913 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 srb->datalen = 0;
915 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200916 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
917 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000918 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200919 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100920 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800921 /*
922 * Check the Key Code Qualifier, if it matches
923 * "Not Ready - medium not present"
924 * (the sense Key equals 0x2 and the ASC is 0x3a)
925 * return immediately as the medium being absent won't change
926 * unless there is a user action.
927 */
928 if ((srb->sense_buf[2] == 0x02) &&
929 (srb->sense_buf[12] == 0x3a))
930 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000931 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100932 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000933
wdenkaffae2b2002-08-17 09:36:01 +0000934 return -1;
935}
936
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100937static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000938{
939 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100940 /* XXX retries */
941 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000942 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100943 memset(&srb->cmd[0], 0, 12);
944 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200945 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100946 srb->datalen = 8;
947 srb->cmdlen = 12;
948 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000949 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100950 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000951
wdenkaffae2b2002-08-17 09:36:01 +0000952 return -1;
953}
954
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
956 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000957{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 memset(&srb->cmd[0], 0, 12);
959 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200960 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100961 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
962 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
963 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
964 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
965 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
966 srb->cmd[8] = (unsigned char) blocks & 0xff;
967 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530968 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100969 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000970}
971
Mahavir Jain127e1082009-11-03 12:22:10 +0530972static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
973 unsigned short blocks)
974{
975 memset(&srb->cmd[0], 0, 12);
976 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200977 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +0530978 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
979 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
980 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
981 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
982 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
983 srb->cmd[8] = (unsigned char) blocks & 0xff;
984 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530985 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +0530986 return ss->transport(srb, ss);
987}
988
wdenkaffae2b2002-08-17 09:36:01 +0000989
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +0200990#ifdef CONFIG_USB_BIN_FIXUP
991/*
992 * Some USB storage devices queried for SCSI identification data respond with
993 * binary strings, which if output to the console freeze the terminal. The
994 * workaround is to modify the vendor and product strings read from such
995 * device with proper values (as reported by 'usb info').
996 *
997 * Vendor and product length limits are taken from the definition of
998 * block_dev_desc_t in include/part.h.
999 */
1000static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1001 unsigned char vendor[],
1002 unsigned char product[]) {
1003 const unsigned char max_vendor_len = 40;
1004 const unsigned char max_product_len = 20;
1005 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001006 strncpy((char *)vendor, "SMSC", max_vendor_len);
1007 strncpy((char *)product, "Flash Media Cntrller",
1008 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001009 }
1010}
1011#endif /* CONFIG_USB_BIN_FIXUP */
1012
Sascha Silbeff8fef52013-06-14 13:07:25 +02001013unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001014 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001015{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001016 lbaint_t start, blks;
1017 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001018 unsigned short smallblks;
1019 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001020 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001021 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001022 ccb *srb = &usb_ccb;
1023
1024 if (blkcnt == 0)
1025 return 0;
1026
1027 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001028 /* Setup device */
Vivek Gautamceb49722013-04-12 16:34:33 +05301029 debug("\nusb_read: dev %d \n", device);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001030 dev = NULL;
1031 for (i = 0; i < USB_MAX_DEVICE; i++) {
1032 dev = usb_get_dev_index(i);
1033 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001034 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001035 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001036 break;
1037 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001038 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001039
1040 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001041 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001042 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001043 start = blknr;
1044 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001045
Vivek Gautamceb49722013-04-12 16:34:33 +05301046 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001047 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001048
wdenkaffae2b2002-08-17 09:36:01 +00001049 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 /* XXX need some comment here */
1051 retry = 2;
1052 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001053 if (blks > USB_MAX_XFER_BLK)
1054 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 else
1056 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001057retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001058 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001059 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001060 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1061 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001062 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301063 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001064 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001065 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001066 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001067 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001068 break;
1069 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001070 start += smallblks;
1071 blks -= smallblks;
1072 buf_addr += srb->datalen;
1073 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001074 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001075
Vivek Gautamceb49722013-04-12 16:34:33 +05301076 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001077 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301078 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079
wdenkaffae2b2002-08-17 09:36:01 +00001080 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001081 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001082 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001083 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001084}
1085
Sascha Silbeff8fef52013-06-14 13:07:25 +02001086unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001087 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301088{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001089 lbaint_t start, blks;
1090 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301091 unsigned short smallblks;
1092 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001093 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301094 int retry, i;
1095 ccb *srb = &usb_ccb;
1096
1097 if (blkcnt == 0)
1098 return 0;
1099
1100 device &= 0xff;
1101 /* Setup device */
Vivek Gautamceb49722013-04-12 16:34:33 +05301102 debug("\nusb_write: dev %d \n", device);
Mahavir Jain127e1082009-11-03 12:22:10 +05301103 dev = NULL;
1104 for (i = 0; i < USB_MAX_DEVICE; i++) {
1105 dev = usb_get_dev_index(i);
1106 if (dev == NULL)
1107 return 0;
1108 if (dev->devnum == usb_dev_desc[device].target)
1109 break;
1110 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001111 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301112
1113 usb_disable_asynch(1); /* asynch transfer not allowed */
1114
1115 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001116 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301117 start = blknr;
1118 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301119
Vivek Gautamceb49722013-04-12 16:34:33 +05301120 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001121 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301122
1123 do {
1124 /* If write fails retry for max retry count else
1125 * return with number of blocks written successfully.
1126 */
1127 retry = 2;
1128 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001129 if (blks > USB_MAX_XFER_BLK)
1130 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301131 else
1132 smallblks = (unsigned short) blks;
1133retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001134 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301135 usb_show_progress();
1136 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1137 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001138 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301139 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001140 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301141 if (retry--)
1142 goto retry_it;
1143 blkcnt -= blks;
1144 break;
1145 }
1146 start += smallblks;
1147 blks -= smallblks;
1148 buf_addr += srb->datalen;
1149 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001150 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301151
Simon Glass4fd074d2014-10-15 04:38:38 -06001152 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1153 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301154
1155 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001156 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001157 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301158 return blkcnt;
1159
1160}
wdenkaffae2b2002-08-17 09:36:01 +00001161
1162/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001163int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1164 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001165{
Tom Rix8f8bd562009-10-31 12:37:38 -05001166 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001167 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301168 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001169 unsigned int flags = 0;
1170
1171 int protocol = 0;
1172 int subclass = 0;
1173
wdenkaffae2b2002-08-17 09:36:01 +00001174 /* let's examine the device now */
1175 iface = &dev->config.if_desc[ifnum];
1176
1177#if 0
1178 /* this is the place to patch some storage devices */
Vivek Gautamceb49722013-04-12 16:34:33 +05301179 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001180 dev->descriptor.idProduct);
1181
1182 if ((dev->descriptor.idVendor) == 0x066b &&
1183 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301184 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001185 protocol = US_PR_CB;
1186 subclass = US_SC_UFI; /* an assumption */
1187 }
1188#endif
1189
1190 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001191 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1192 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1193 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001194 /* if it's not a mass storage, we go no further */
1195 return 0;
1196 }
1197
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001198 memset(ss, 0, sizeof(struct us_data));
1199
wdenkaffae2b2002-08-17 09:36:01 +00001200 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301201 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001202
1203 /* Initialize the us_data structure with some useful info */
1204 ss->flags = flags;
1205 ss->ifnum = ifnum;
1206 ss->pusb_dev = dev;
1207 ss->attention_done = 0;
1208
1209 /* If the device has subclass and protocol, then use that. Otherwise,
1210 * take data from the specific interface.
1211 */
1212 if (subclass) {
1213 ss->subclass = subclass;
1214 ss->protocol = protocol;
1215 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001216 ss->subclass = iface->desc.bInterfaceSubClass;
1217 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001218 }
1219
1220 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301221 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001222 switch (ss->protocol) {
1223 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301224 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001225 ss->transport = usb_stor_CB_transport;
1226 ss->transport_reset = usb_stor_CB_reset;
1227 break;
1228
1229 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301230 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001231 ss->transport = usb_stor_CB_transport;
1232 ss->transport_reset = usb_stor_CB_reset;
1233 break;
wdenk149dded2003-09-10 18:20:28 +00001234 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301235 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001236 ss->transport = usb_stor_BBB_transport;
1237 ss->transport_reset = usb_stor_BBB_reset;
1238 break;
wdenkaffae2b2002-08-17 09:36:01 +00001239 default:
wdenk80885a92004-02-26 23:46:20 +00001240 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001241 return 0;
1242 break;
1243 }
1244
1245 /*
1246 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1247 * An optional interrupt is OK (necessary for CBI protocol).
1248 * We will ignore any others.
1249 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001250 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301251 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001252 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301253 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001254 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301255 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1256 ss->ep_in = ep_desc->bEndpointAddress &
1257 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001258 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001259 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301260 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001261 USB_ENDPOINT_NUMBER_MASK;
1262 }
1263
1264 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301265 if ((ep_desc->bmAttributes &
1266 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1267 ss->ep_int = ep_desc->bEndpointAddress &
1268 USB_ENDPOINT_NUMBER_MASK;
1269 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001270 }
1271 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301272 debug("Endpoints In %d Out %d Int %d\n",
1273 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001274
1275 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001276 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001277 !ss->ep_in || !ss->ep_out ||
1278 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301279 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001280 return 0;
1281 }
1282 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001283 /* We only handle certain protocols. Currently, these are
1284 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001285 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001286 */
wdenk80885a92004-02-26 23:46:20 +00001287 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1288 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001289 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001290 return 0;
1291 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001292 if (ss->ep_int) {
1293 /* we had found an interrupt endpoint, prepare irq pipe
1294 * set up the IRQ pipe and handler
1295 */
wdenkaffae2b2002-08-17 09:36:01 +00001296 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1297 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1298 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001299 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001300 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001301 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001302 return 1;
1303}
1304
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001305int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1306 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001307{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001308 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001309 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1310 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1311 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001312 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001313
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001314 pccb->pdata = usb_stor_buf;
1315
1316 dev_desc->target = dev->devnum;
1317 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301318 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001319
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001320 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001321 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001322
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001323 perq = usb_stor_buf[0];
1324 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001325
Soeren Moch6a559bb2014-11-08 07:02:14 +01001326 /*
1327 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1328 * they would not respond to test_unit_ready .
1329 */
1330 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001331 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001332 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001333 if ((modi&0x80) == 0x80) {
1334 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001335 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001336 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001337 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1338 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1339 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001340 dev_desc->vendor[8] = 0;
1341 dev_desc->product[16] = 0;
1342 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001343#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001344 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1345 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001346#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301347 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1348 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001349 if (usb_test_unit_ready(pccb, ss)) {
1350 printf("Device NOT ready\n"
1351 " Request Sense returned %02X %02X %02X\n",
1352 pccb->sense_buf[2], pccb->sense_buf[12],
1353 pccb->sense_buf[13]);
1354 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001355 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001356 return 1;
1357 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001358 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001359 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001360 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001361 memset(pccb->pdata, 0, 8);
1362 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001363 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001364 cap[0] = 2880;
1365 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001366 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001367 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001368 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001369#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001370 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1371 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001372
Christian Eggersc9182612008-05-21 22:12:00 +02001373 cap[0] = cpu_to_be32(cap[0]);
1374 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001375#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001376
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001377 capacity = be32_to_cpu(cap[0]) + 1;
1378 blksz = be32_to_cpu(cap[1]);
1379
1380 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1381 dev_desc->lba = capacity;
1382 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001383 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001384 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301385 debug(" address %d\n", dev_desc->target);
1386 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001387
1388 init_part(dev_desc);
1389
Vivek Gautamceb49722013-04-12 16:34:33 +05301390 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001391 return 1;
1392}