blob: 4fa6538db58af627ffce1ae39b29e84ab2c6b510 [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
Simon Glassacf277a2015-03-25 12:22:16 -060012 * Driver model conversion:
13 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000014 *
wdenk149dded2003-09-10 18:20:28 +000015 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020016 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000017 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020018 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000019 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000020 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020021 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +000022 */
23
24/* Note:
25 * Currently only the CBI transport protocoll has been implemented, and it
26 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
27 * transport protocoll may work as well.
28 */
wdenk149dded2003-09-10 18:20:28 +000029/*
30 * New Note:
31 * Support for USB Mass Storage Devices (BBB) has been added. It has
32 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000033 */
wdenkaffae2b2002-08-17 09:36:01 +000034
35
wdenkaffae2b2002-08-17 09:36:01 +000036#include <common.h>
37#include <command.h>
Simon Glassacf277a2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glass91557572015-03-25 12:22:15 -060039#include <errno.h>
Simon Glass4fd074d2014-10-15 04:38:38 -060040#include <inttypes.h>
Simon Glass05108132015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glasscf92e052015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggersc9182612008-05-21 22:12:00 +020043#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
wdenkaffae2b2002-08-17 09:36:01 +000046
Grant Likely735dd972007-02-20 09:04:34 +010047#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000048#include <usb.h>
49
wdenk80885a92004-02-26 23:46:20 +000050#undef BBB_COMDAT_TRACE
51#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000052
wdenkaffae2b2002-08-17 09:36:01 +000053#include <scsi.h>
54/* direction table -- this indicates the direction of the data
55 * transfer for each command code -- a 1 indicates input
56 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040057static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000058 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
59 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
62};
63#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
64
Puneet Saxenaf5766132012-04-03 14:56:06 +053065static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010066static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000067
wdenkaffae2b2002-08-17 09:36:01 +000068#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
71static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
72
73struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010074typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
75typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000076
77struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010078 struct usb_device *pusb_dev; /* this usb_device */
79
80 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020081# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010082 unsigned char ifnum; /* interface number */
83 unsigned char ep_in; /* in endpoint */
84 unsigned char ep_out; /* out ....... */
85 unsigned char ep_int; /* interrupt . */
86 unsigned char subclass; /* as in overview */
87 unsigned char protocol; /* .............. */
88 unsigned char attention_done; /* force attn on first cmd */
89 unsigned short ip_data; /* interrupt data */
90 int action; /* what to do */
91 int ip_wanted; /* needed */
92 int *irq_handle; /* for USB int requests */
93 unsigned int irqpipe; /* pipe for release_irq */
94 unsigned char irqmaxp; /* max packed for irq Pipe */
95 unsigned char irqinterval; /* Intervall for IRQ Pipe */
96 ccb *srb; /* current srb */
97 trans_reset transport_reset; /* reset routine */
98 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000099};
100
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200101#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000102/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200103 * The U-Boot EHCI driver can handle any transfer length as long as there is
104 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
105 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000106 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200107#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200108#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200109#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200110#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000111
wdenkaffae2b2002-08-17 09:36:01 +0000112static struct us_data usb_stor[USB_MAX_STOR_DEV];
113
wdenk80885a92004-02-26 23:46:20 +0000114#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000115#define USB_STOR_TRANSPORT_FAILED -1
116#define USB_STOR_TRANSPORT_ERROR -2
117
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100118int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
119 block_dev_desc_t *dev_desc);
120int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
121 struct us_data *ss);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200122unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000123 lbaint_t blkcnt, void *buffer);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200124unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000125 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000126void uhci_show_temp_int_td(void);
127
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000128#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000129block_dev_desc_t *usb_stor_get_dev(int index)
130{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200131 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000132}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000133#endif
wdenkaffae2b2002-08-17 09:36:01 +0000134
Kim Phillips199adb62012-10-29 13:34:32 +0000135static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000136{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200137 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000138}
139
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100140/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200141 * show info on storage devices; 'usb start/init' must be invoked earlier
142 * as we only retrieve structures populated during devices initialization
143 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100144int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200145{
146 int i;
147
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100148 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200149 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100150 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200151 dev_print(&usb_dev_desc[i]);
152 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100153 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100154 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700155
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100156 printf("No storage devices, perhaps not 'usb start'ed..?\n");
157 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200158}
159
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200160static unsigned int usb_get_max_lun(struct us_data *us)
161{
162 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530163 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200164 len = usb_control_msg(us->pusb_dev,
165 usb_rcvctrlpipe(us->pusb_dev, 0),
166 US_BBB_GET_MAX_LUN,
167 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
168 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530169 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200170 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530171 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530172 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200173}
174
Simon Glass91557572015-03-25 12:22:15 -0600175static int usb_stor_probe_device(struct usb_device *dev)
176{
177 if (dev == NULL)
178 return -ENOENT; /* no more devices available */
179
180 debug("\n\nProbing for storage\n");
181 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
182 /* OK, it's a storage device. Iterate over its LUNs
183 * and populate `usb_dev_desc'.
184 */
185 int lun, max_lun, start = usb_max_devs;
186
187 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
188 for (lun = 0;
189 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
190 lun++) {
191 struct block_dev_desc *blkdev;
192
193 blkdev = &usb_dev_desc[usb_max_devs];
194 memset(blkdev, '\0', sizeof(block_dev_desc_t));
195 blkdev->if_type = IF_TYPE_USB;
196 blkdev->dev = usb_max_devs;
197 blkdev->part_type = PART_TYPE_UNKNOWN;
198 blkdev->target = 0xff;
199 blkdev->type = DEV_TYPE_UNKNOWN;
200 blkdev->block_read = usb_stor_read;
201 blkdev->block_write = usb_stor_write;
202 blkdev->lun = lun;
203 blkdev->priv = dev;
204
205 if (usb_stor_get_info(dev, &usb_stor[start],
206 &usb_dev_desc[usb_max_devs]) ==
207 1) {
208 usb_max_devs++;
209 debug("%s: Found device %p\n", __func__, dev);
210 }
211 }
212 }
213
214 /* if storage device */
215 if (usb_max_devs == USB_MAX_STOR_DEV) {
216 printf("max USB Storage Device reached: %d stopping\n",
217 usb_max_devs);
218 return -ENOSPC;
219 }
220
221 return 0;
222}
223
224void usb_stor_reset(void)
225{
226 usb_max_devs = 0;
227}
228
Simon Glassacf277a2015-03-25 12:22:16 -0600229#ifndef CONFIG_DM_USB
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100230/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200231 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000232 * to the user if mode = 1
233 * returns current device or -1 if no
234 */
235int usb_stor_scan(int mode)
236{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600237 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000238
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100239 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200240 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100241
wdenkaffae2b2002-08-17 09:36:01 +0000242 usb_disable_asynch(1); /* asynch transfer not allowed */
243
Simon Glass91557572015-03-25 12:22:15 -0600244 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100245 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600246 struct usb_device *dev;
247
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100248 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530249 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600250 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000251 break;
wdenkaffae2b2002-08-17 09:36:01 +0000252 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200253
wdenkaffae2b2002-08-17 09:36:01 +0000254 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200255 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100256 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000257 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100258 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000259}
Simon Glassacf277a2015-03-25 12:22:16 -0600260#endif
wdenkaffae2b2002-08-17 09:36:01 +0000261
262static int usb_stor_irq(struct usb_device *dev)
263{
264 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100265 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000266
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100267 if (us->ip_wanted)
268 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000269 return 0;
270}
271
272
Vivek Gautamceb49722013-04-12 16:34:33 +0530273#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000274
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100275static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000276{
277 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100278 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
279 for (i = 0; i < 12; i++)
280 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000281 printf("\n");
282}
283
284static void display_int_status(unsigned long tmp)
285{
286 printf("Status: %s %s %s %s %s %s %s\n",
287 (tmp & USB_ST_ACTIVE) ? "Active" : "",
288 (tmp & USB_ST_STALLED) ? "Stalled" : "",
289 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
290 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
291 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
292 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
293 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
294}
295#endif
296/***********************************************************************
297 * Data transfer routines
298 ***********************************************************************/
299
300static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
301{
302 int max_size;
303 int this_xfer;
304 int result;
305 int partial;
306 int maxtry;
307 int stat;
308
309 /* determine the maximum packet size for these transfers */
310 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
311
312 /* while we have data left to transfer */
313 while (length) {
314
315 /* calculate how long this will be -- maximum or a remainder */
316 this_xfer = length > max_size ? max_size : length;
317 length -= this_xfer;
318
319 /* setup the retry counter */
320 maxtry = 10;
321
322 /* set up the transfer loop */
323 do {
324 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600325 debug("Bulk xfer 0x%lx(%d) try #%d\n",
326 (ulong)map_to_sysmem(buf), this_xfer,
327 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000328 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100329 this_xfer, &partial,
330 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530331 debug("bulk_msg returned %d xferred %d/%d\n",
332 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100333 if (us->pusb_dev->status != 0) {
334 /* if we stall, we need to clear it before
335 * we go on
336 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530337#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000338 display_int_status(us->pusb_dev->status);
339#endif
340 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530341 debug("stalled ->clearing endpoint" \
342 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000343 stat = us->pusb_dev->status;
344 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100345 us->pusb_dev->status = stat;
346 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530347 debug("bulk transferred" \
348 "with error %lX," \
349 " but data ok\n",
350 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000351 return 0;
352 }
353 else
354 return result;
355 }
356 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530357 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000358 return result;
359 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530360 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100361 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530362 debug(" %ld, but data ok\n",
363 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000364 return 0;
365 }
366 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530367 debug(" %ld, data %d\n",
368 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000369 if (!maxtry--)
370 return result;
371 }
372 /* update to show what data was transferred */
373 this_xfer -= partial;
374 buf += partial;
375 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100376 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000377 }
378
379 /* if we get here, we're done and successful */
380 return 0;
381}
382
wdenk149dded2003-09-10 18:20:28 +0000383static int usb_stor_BBB_reset(struct us_data *us)
384{
385 int result;
386 unsigned int pipe;
387
388 /*
389 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
390 *
391 * For Reset Recovery the host shall issue in the following order:
392 * a) a Bulk-Only Mass Storage Reset
393 * b) a Clear Feature HALT to the Bulk-In endpoint
394 * c) a Clear Feature HALT to the Bulk-Out endpoint
395 *
396 * This is done in 3 steps.
397 *
398 * If the reset doesn't succeed, the device should be port reset.
399 *
400 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
401 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530402 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100403 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
404 US_BBB_RESET,
405 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000406 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200407
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100408 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530409 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000410 return -1;
411 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200412
wdenk149dded2003-09-10 18:20:28 +0000413 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000414 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530415 debug("BBB_reset result %d: status %lX reset\n",
416 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000417 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
418 result = usb_clear_halt(us->pusb_dev, pipe);
419 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000420 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530421 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
422 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000423 /* long wait for reset */
424 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
425 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000426 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530427 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
428 result, us->pusb_dev->status);
429 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000430 return 0;
431}
432
wdenkaffae2b2002-08-17 09:36:01 +0000433/* FIXME: this reset function doesn't really reset the port, and it
434 * should. Actually it should probably do what it's doing here, and
435 * reset the port physically
436 */
437static int usb_stor_CB_reset(struct us_data *us)
438{
439 unsigned char cmd[12];
440 int result;
441
Vivek Gautamceb49722013-04-12 16:34:33 +0530442 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100443 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000444 cmd[0] = SCSI_SEND_DIAG;
445 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100446 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
447 US_CBI_ADSC,
448 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
449 0, us->ifnum, cmd, sizeof(cmd),
450 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000451
452 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000453 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530454 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
455 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000456 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
457 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
458
Vivek Gautamceb49722013-04-12 16:34:33 +0530459 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000460 return 0;
461}
462
wdenk149dded2003-09-10 18:20:28 +0000463/*
464 * Set up the command for a BBB device. Note that the actual SCSI
465 * command is copied into cbw.CBWCDB.
466 */
Kim Phillips199adb62012-10-29 13:34:32 +0000467static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000468{
469 int result;
470 int actlen;
471 int dir_in;
472 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600473 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000474
475 dir_in = US_DIRECTION(srb->cmd[0]);
476
477#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530478 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100479 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
480 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000481 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100482 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000483 printf("cmd[%d] %#x ", result, srb->cmd[result]);
484 printf("\n");
485 }
486#endif
487 /* sanity checks */
488 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530489 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000490 return -1;
491 }
492
493 /* always OUT to the ep */
494 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
495
Puneet Saxenaf5766132012-04-03 14:56:06 +0530496 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
497 cbw->dCBWTag = cpu_to_le32(CBWTag++);
498 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
499 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
500 cbw->bCBWLUN = srb->lun;
501 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000502 /* copy the command data into the CBW command data buffer */
503 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300504
Puneet Saxenaf5766132012-04-03 14:56:06 +0530505 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
506 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100507 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000508 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530509 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000510 return result;
511}
512
wdenkaffae2b2002-08-17 09:36:01 +0000513/* FIXME: we also need a CBI_command which sets up the completion
514 * interrupt, and waits for it
515 */
Kim Phillips199adb62012-10-29 13:34:32 +0000516static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000517{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200518 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100519 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000520 unsigned int pipe;
521 unsigned long status;
522
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100523 retry = 5;
524 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000525
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100526 if (dir_in)
527 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
528 else
529 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
530
531 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530532 debug("CBI gets a command: Try %d\n", 5 - retry);
533#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000534 usb_show_srb(srb);
535#endif
536 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100537 result = usb_control_msg(us->pusb_dev,
538 usb_sndctrlpipe(us->pusb_dev , 0),
539 US_CBI_ADSC,
540 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000541 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100542 srb->cmd, srb->cmdlen,
543 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530544 debug("CB_transport: control msg returned %d, status %lX\n",
545 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000546 /* check the return code for the command */
547 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100548 if (us->pusb_dev->status & USB_ST_STALLED) {
549 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530550 debug(" stall during command found," \
551 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100552 usb_clear_halt(us->pusb_dev,
553 usb_sndctrlpipe(us->pusb_dev, 0));
554 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000555 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530556 debug(" error during command %02X" \
557 " Stat = %lX\n", srb->cmd[0],
558 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000559 return result;
560 }
561 /* transfer the data payload for this command, if one exists*/
562
Vivek Gautamceb49722013-04-12 16:34:33 +0530563 debug("CB_transport: control msg returned %d," \
564 " direction is %s to go 0x%lx\n", result,
565 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000566 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100567 result = us_one_transfer(us, pipe, (char *)srb->pdata,
568 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530569 debug("CBI attempted to transfer data," \
570 " result is %d status %lX, len %d\n",
571 result, us->pusb_dev->status,
572 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100573 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000574 break;
575 } /* if (srb->datalen) */
576 else
577 break;
578 }
579 /* return result */
580
581 return result;
582}
583
584
Kim Phillips199adb62012-10-29 13:34:32 +0000585static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000586{
587 int timeout;
588
wdenk80885a92004-02-26 23:46:20 +0000589 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100590 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000591 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
592 timeout = 1000;
593 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300594 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000595 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000596 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000597 }
598 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100599 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000600 us->ip_wanted = 0;
601 return USB_STOR_TRANSPORT_ERROR;
602 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530603 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
604 us->ip_data, us->pusb_dev->irq_act_len,
605 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000606 /* UFI gives us ASC and ASCQ, like a request sense */
607 if (us->subclass == US_SC_UFI) {
608 if (srb->cmd[0] == SCSI_REQ_SENSE ||
609 srb->cmd[0] == SCSI_INQUIRY)
610 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000611 else if (us->ip_data)
612 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000613 else
wdenk80885a92004-02-26 23:46:20 +0000614 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000615 }
616 /* otherwise, we interpret the data normally */
617 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000618 case 0x0001:
619 return USB_STOR_TRANSPORT_GOOD;
620 case 0x0002:
621 return USB_STOR_TRANSPORT_FAILED;
622 default:
623 return USB_STOR_TRANSPORT_ERROR;
624 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000625 return USB_STOR_TRANSPORT_ERROR;
626}
627
628#define USB_TRANSPORT_UNKNOWN_RETRY 5
629#define USB_TRANSPORT_NOT_READY_RETRY 10
630
wdenk149dded2003-09-10 18:20:28 +0000631/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000632static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000633{
634 int result;
635
636 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100637 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000638 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000639 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000640 return result;
641}
642
Kim Phillips199adb62012-10-29 13:34:32 +0000643static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000644{
645 int result, retry;
646 int dir_in;
647 int actlen, data_actlen;
648 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600649 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000650#ifdef BBB_XPORT_TRACE
651 unsigned char *ptr;
652 int index;
653#endif
654
655 dir_in = US_DIRECTION(srb->cmd[0]);
656
657 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530658 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000659 result = usb_stor_BBB_comdat(srb, us);
660 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530661 debug("failed to send CBW status %ld\n",
662 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000663 usb_stor_BBB_reset(us);
664 return USB_STOR_TRANSPORT_FAILED;
665 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200666 if (!(us->flags & USB_READY))
667 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000668 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
669 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
670 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000671 data_actlen = 0;
672 /* no data, go immediately to the STATUS phase */
673 if (srb->datalen == 0)
674 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530675 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000676 if (dir_in)
677 pipe = pipein;
678 else
679 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300680
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100681 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
682 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000683 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100684 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530685 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000686 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100687 result = usb_stor_BBB_clear_endpt_stall(us,
688 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000689 if (result >= 0)
690 /* continue on to STATUS phase */
691 goto st;
692 }
693 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530694 debug("usb_bulk_msg error status %ld\n",
695 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000696 usb_stor_BBB_reset(us);
697 return USB_STOR_TRANSPORT_FAILED;
698 }
699#ifdef BBB_XPORT_TRACE
700 for (index = 0; index < data_actlen; index++)
701 printf("pdata[%d] %#x ", index, srb->pdata[index]);
702 printf("\n");
703#endif
704 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100705st:
wdenk149dded2003-09-10 18:20:28 +0000706 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100707again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530708 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530709 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200710 &actlen, USB_CNTL_TIMEOUT*5);
711
wdenk149dded2003-09-10 18:20:28 +0000712 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100713 if ((result < 0) && (retry < 1) &&
714 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530715 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000716 /* clear the STALL on the endpoint */
717 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
718 if (result >= 0 && (retry++ < 1))
719 /* do a retry */
720 goto again;
721 }
722 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530723 debug("usb_bulk_msg error status %ld\n",
724 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
727 }
728#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530729 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000730 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
731 printf("ptr[%d] %#x ", index, ptr[index]);
732 printf("\n");
733#endif
734 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530735 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000736 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
737 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530738 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530739 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000740 usb_stor_BBB_reset(us);
741 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530742 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530743 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000744 usb_stor_BBB_reset(us);
745 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530746 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530747 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000748 usb_stor_BBB_reset(us);
749 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530750 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530751 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000752 usb_stor_BBB_reset(us);
753 return USB_STOR_TRANSPORT_FAILED;
754 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530755 debug("transferred %dB instead of %ldB\n",
756 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000757 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530758 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530759 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000760 return USB_STOR_TRANSPORT_FAILED;
761 }
762
763 return result;
764}
765
Kim Phillips199adb62012-10-29 13:34:32 +0000766static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000767{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100768 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000769 ccb *psrb;
770 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100771 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000772
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200773 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100774 status = USB_STOR_TRANSPORT_GOOD;
775 retry = 0;
776 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000777 /* issue the command */
778do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100779 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530780 debug("command / Data returned %d, status %lX\n",
781 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000782 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100783 if (us->protocol == US_PR_CBI) {
784 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000785 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100786 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530787 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000788 return status;
789 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100790 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
791 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
792 if (!us->ip_data) {
793 /* if the status is good, report it */
794 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530795 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000796 return status;
797 }
798 }
799 }
800 /* do we have to issue an auto request? */
801 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100802 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530803 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000804 us->transport_reset(us);
805 return USB_STOR_TRANSPORT_ERROR;
806 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100807 if ((us->protocol == US_PR_CBI) &&
808 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
809 (srb->cmd[0] == SCSI_INQUIRY))) {
810 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530811 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000812 return USB_STOR_TRANSPORT_GOOD;
813 }
814 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100815 memset(&psrb->cmd[0], 0, 12);
816 psrb->cmd[0] = SCSI_REQ_SENSE;
817 psrb->cmd[1] = srb->lun << 5;
818 psrb->cmd[4] = 18;
819 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200820 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100821 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000822 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100823 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530824 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000825 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100826 if (us->protocol == US_PR_CBI)
827 status = usb_stor_CBI_get_status(psrb, us);
828
829 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530830 debug(" AUTO REQUEST ERROR %ld\n",
831 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000832 return USB_STOR_TRANSPORT_ERROR;
833 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530834 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
835 srb->sense_buf[0], srb->sense_buf[2],
836 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000837 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100838 if ((srb->sense_buf[2] == 0) &&
839 (srb->sense_buf[12] == 0) &&
840 (srb->sense_buf[13] == 0)) {
841 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000842 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100843 }
844
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100846 switch (srb->sense_buf[2]) {
847 case 0x01:
848 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000849 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000850 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100851 case 0x02:
852 /* Not Ready */
853 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
854 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
855 " 0x%02X (NOT READY)\n", srb->cmd[0],
856 srb->sense_buf[0], srb->sense_buf[2],
857 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000858 return USB_STOR_TRANSPORT_FAILED;
859 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000860 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000861 goto do_retry;
862 }
863 break;
864 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100865 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
866 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
867 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
868 srb->sense_buf[2], srb->sense_buf[12],
869 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000870 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100871 } else
wdenk149dded2003-09-10 18:20:28 +0000872 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000873 break;
wdenkaffae2b2002-08-17 09:36:01 +0000874 }
875 return USB_STOR_TRANSPORT_FAILED;
876}
877
878
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100879static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000880{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100881 int retry, i;
882 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000883 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100884 memset(&srb->cmd[0], 0, 12);
885 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200886 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100887 srb->cmd[4] = 36;
888 srb->datalen = 36;
889 srb->cmdlen = 12;
890 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530891 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100892 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000893 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200894 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000895
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100896 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000897 printf("error in inquiry\n");
898 return -1;
899 }
900 return 0;
901}
902
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100903static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000904{
905 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000906
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100907 ptr = (char *)srb->pdata;
908 memset(&srb->cmd[0], 0, 12);
909 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200910 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911 srb->cmd[4] = 18;
912 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200913 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 srb->cmdlen = 12;
915 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530916 debug("Request Sense returned %02X %02X %02X\n",
917 srb->sense_buf[2], srb->sense_buf[12],
918 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100919 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000920 return 0;
921}
922
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000924{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200925 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000926
wdenkaffae2b2002-08-17 09:36:01 +0000927 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100928 memset(&srb->cmd[0], 0, 12);
929 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200930 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100931 srb->datalen = 0;
932 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200933 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
934 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000935 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200936 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100937 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800938 /*
939 * Check the Key Code Qualifier, if it matches
940 * "Not Ready - medium not present"
941 * (the sense Key equals 0x2 and the ASC is 0x3a)
942 * return immediately as the medium being absent won't change
943 * unless there is a user action.
944 */
945 if ((srb->sense_buf[2] == 0x02) &&
946 (srb->sense_buf[12] == 0x3a))
947 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000948 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100949 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000950
wdenkaffae2b2002-08-17 09:36:01 +0000951 return -1;
952}
953
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100954static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000955{
956 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100957 /* XXX retries */
958 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000959 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100960 memset(&srb->cmd[0], 0, 12);
961 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200962 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100963 srb->datalen = 8;
964 srb->cmdlen = 12;
965 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000966 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000968
wdenkaffae2b2002-08-17 09:36:01 +0000969 return -1;
970}
971
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100972static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
973 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000974{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100975 memset(&srb->cmd[0], 0, 12);
976 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200977 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100978 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("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100986 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000987}
988
Mahavir Jain127e1082009-11-03 12:22:10 +0530989static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
990 unsigned short blocks)
991{
992 memset(&srb->cmd[0], 0, 12);
993 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200994 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +0530995 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
996 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
997 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
998 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
999 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1000 srb->cmd[8] = (unsigned char) blocks & 0xff;
1001 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301002 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301003 return ss->transport(srb, ss);
1004}
1005
wdenkaffae2b2002-08-17 09:36:01 +00001006
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001007#ifdef CONFIG_USB_BIN_FIXUP
1008/*
1009 * Some USB storage devices queried for SCSI identification data respond with
1010 * binary strings, which if output to the console freeze the terminal. The
1011 * workaround is to modify the vendor and product strings read from such
1012 * device with proper values (as reported by 'usb info').
1013 *
1014 * Vendor and product length limits are taken from the definition of
1015 * block_dev_desc_t in include/part.h.
1016 */
1017static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1018 unsigned char vendor[],
1019 unsigned char product[]) {
1020 const unsigned char max_vendor_len = 40;
1021 const unsigned char max_product_len = 20;
1022 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001023 strncpy((char *)vendor, "SMSC", max_vendor_len);
1024 strncpy((char *)product, "Flash Media Cntrller",
1025 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001026 }
1027}
1028#endif /* CONFIG_USB_BIN_FIXUP */
1029
Sascha Silbeff8fef52013-06-14 13:07:25 +02001030unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001031 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001032{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001033 lbaint_t start, blks;
1034 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001035 unsigned short smallblks;
1036 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001037 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001038 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001039 ccb *srb = &usb_ccb;
1040
1041 if (blkcnt == 0)
1042 return 0;
1043
1044 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001045 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001046 debug("\nusb_read: dev %d\n", device);
1047 dev = usb_dev_desc[device].priv;
1048 if (!dev) {
1049 debug("%s: No device\n", __func__);
1050 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001051 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001052 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001053
1054 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001056 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057 start = blknr;
1058 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001059
Vivek Gautamceb49722013-04-12 16:34:33 +05301060 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001061 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001062
wdenkaffae2b2002-08-17 09:36:01 +00001063 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 /* XXX need some comment here */
1065 retry = 2;
1066 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001067 if (blks > USB_MAX_XFER_BLK)
1068 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 else
1070 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001071retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001072 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001073 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001074 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1075 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001076 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301077 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001078 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001080 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001081 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001082 break;
1083 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001084 start += smallblks;
1085 blks -= smallblks;
1086 buf_addr += srb->datalen;
1087 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001088 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001089
Vivek Gautamceb49722013-04-12 16:34:33 +05301090 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001091 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301092 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001093
wdenkaffae2b2002-08-17 09:36:01 +00001094 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001095 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001096 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001097 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001098}
1099
Sascha Silbeff8fef52013-06-14 13:07:25 +02001100unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001101 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301102{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001103 lbaint_t start, blks;
1104 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301105 unsigned short smallblks;
1106 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001107 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001108 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301109 ccb *srb = &usb_ccb;
1110
1111 if (blkcnt == 0)
1112 return 0;
1113
1114 device &= 0xff;
1115 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001116 debug("\nusb_write: dev %d\n", device);
1117 dev = usb_dev_desc[device].priv;
1118 if (!dev)
1119 return 0;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001120 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301121
1122 usb_disable_asynch(1); /* asynch transfer not allowed */
1123
1124 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001125 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301126 start = blknr;
1127 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301128
Vivek Gautamceb49722013-04-12 16:34:33 +05301129 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001130 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301131
1132 do {
1133 /* If write fails retry for max retry count else
1134 * return with number of blocks written successfully.
1135 */
1136 retry = 2;
1137 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001138 if (blks > USB_MAX_XFER_BLK)
1139 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301140 else
1141 smallblks = (unsigned short) blks;
1142retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001143 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301144 usb_show_progress();
1145 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1146 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001147 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301148 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001149 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301150 if (retry--)
1151 goto retry_it;
1152 blkcnt -= blks;
1153 break;
1154 }
1155 start += smallblks;
1156 blks -= smallblks;
1157 buf_addr += srb->datalen;
1158 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001159 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301160
Simon Glass4fd074d2014-10-15 04:38:38 -06001161 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1162 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301163
1164 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001165 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001166 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301167 return blkcnt;
1168
1169}
wdenkaffae2b2002-08-17 09:36:01 +00001170
1171/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001172int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1173 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001174{
Tom Rix8f8bd562009-10-31 12:37:38 -05001175 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001176 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301177 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001178 unsigned int flags = 0;
1179
wdenkaffae2b2002-08-17 09:36:01 +00001180 /* let's examine the device now */
1181 iface = &dev->config.if_desc[ifnum];
1182
wdenkaffae2b2002-08-17 09:36:01 +00001183 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001184 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1185 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1186 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001187 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001188 /* if it's not a mass storage, we go no further */
1189 return 0;
1190 }
1191
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001192 memset(ss, 0, sizeof(struct us_data));
1193
wdenkaffae2b2002-08-17 09:36:01 +00001194 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301195 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001196
1197 /* Initialize the us_data structure with some useful info */
1198 ss->flags = flags;
1199 ss->ifnum = ifnum;
1200 ss->pusb_dev = dev;
1201 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001202 ss->subclass = iface->desc.bInterfaceSubClass;
1203 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001204
1205 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301206 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001207 switch (ss->protocol) {
1208 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301209 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001210 ss->transport = usb_stor_CB_transport;
1211 ss->transport_reset = usb_stor_CB_reset;
1212 break;
1213
1214 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301215 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001216 ss->transport = usb_stor_CB_transport;
1217 ss->transport_reset = usb_stor_CB_reset;
1218 break;
wdenk149dded2003-09-10 18:20:28 +00001219 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301220 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001221 ss->transport = usb_stor_BBB_transport;
1222 ss->transport_reset = usb_stor_BBB_reset;
1223 break;
wdenkaffae2b2002-08-17 09:36:01 +00001224 default:
wdenk80885a92004-02-26 23:46:20 +00001225 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001226 return 0;
1227 break;
1228 }
1229
1230 /*
1231 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1232 * An optional interrupt is OK (necessary for CBI protocol).
1233 * We will ignore any others.
1234 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001235 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301236 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001237 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301238 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001239 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301240 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1241 ss->ep_in = ep_desc->bEndpointAddress &
1242 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001243 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001244 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301245 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001246 USB_ENDPOINT_NUMBER_MASK;
1247 }
1248
1249 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301250 if ((ep_desc->bmAttributes &
1251 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1252 ss->ep_int = ep_desc->bEndpointAddress &
1253 USB_ENDPOINT_NUMBER_MASK;
1254 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001255 }
1256 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301257 debug("Endpoints In %d Out %d Int %d\n",
1258 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001259
1260 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001261 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001262 !ss->ep_in || !ss->ep_out ||
1263 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301264 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001265 return 0;
1266 }
1267 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001268 /* We only handle certain protocols. Currently, these are
1269 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001270 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001271 */
wdenk80885a92004-02-26 23:46:20 +00001272 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1273 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001274 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001275 return 0;
1276 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001277 if (ss->ep_int) {
1278 /* we had found an interrupt endpoint, prepare irq pipe
1279 * set up the IRQ pipe and handler
1280 */
wdenkaffae2b2002-08-17 09:36:01 +00001281 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1282 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1283 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001284 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001285 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001286 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001287 return 1;
1288}
1289
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001290int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1291 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001292{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001293 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001294 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1295 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1296 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001297 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001298
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001299 pccb->pdata = usb_stor_buf;
1300
1301 dev_desc->target = dev->devnum;
1302 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301303 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001304
Simon Glass1d5827a2015-03-25 12:22:12 -06001305 if (usb_inquiry(pccb, ss)) {
1306 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001307 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001308 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001309
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001310 perq = usb_stor_buf[0];
1311 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001312
Soeren Moch6a559bb2014-11-08 07:02:14 +01001313 /*
1314 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1315 * they would not respond to test_unit_ready .
1316 */
1317 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001318 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001319 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001320 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001321 if ((modi&0x80) == 0x80) {
1322 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001323 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001324 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001325 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1326 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1327 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001328 dev_desc->vendor[8] = 0;
1329 dev_desc->product[16] = 0;
1330 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001331#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001332 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1333 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001334#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301335 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1336 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001337 if (usb_test_unit_ready(pccb, ss)) {
1338 printf("Device NOT ready\n"
1339 " Request Sense returned %02X %02X %02X\n",
1340 pccb->sense_buf[2], pccb->sense_buf[12],
1341 pccb->sense_buf[13]);
1342 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001343 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001344 return 1;
1345 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001346 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001347 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001348 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001349 memset(pccb->pdata, 0, 8);
1350 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001351 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001352 cap[0] = 2880;
1353 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001354 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001355 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001356 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001357#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001358 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1359 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001360
Christian Eggersc9182612008-05-21 22:12:00 +02001361 cap[0] = cpu_to_be32(cap[0]);
1362 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001363#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001364
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001365 capacity = be32_to_cpu(cap[0]) + 1;
1366 blksz = be32_to_cpu(cap[1]);
1367
1368 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1369 dev_desc->lba = capacity;
1370 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001371 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001372 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301373 debug(" address %d\n", dev_desc->target);
1374 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001375
1376 init_part(dev_desc);
1377
Vivek Gautamceb49722013-04-12 16:34:33 +05301378 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001379 return 1;
1380}
Simon Glassacf277a2015-03-25 12:22:16 -06001381
1382#ifdef CONFIG_DM_USB
1383
1384static int usb_mass_storage_probe(struct udevice *dev)
1385{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001386 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001387 int ret;
1388
1389 usb_disable_asynch(1); /* asynch transfer not allowed */
1390 ret = usb_stor_probe_device(udev);
1391 usb_disable_asynch(0); /* asynch transfer allowed */
1392
1393 return ret;
1394}
1395
1396static const struct udevice_id usb_mass_storage_ids[] = {
1397 { .compatible = "usb-mass-storage" },
1398 { }
1399};
1400
1401U_BOOT_DRIVER(usb_mass_storage) = {
1402 .name = "usb_mass_storage",
1403 .id = UCLASS_MASS_STORAGE,
1404 .of_match = usb_mass_storage_ids,
1405 .probe = usb_mass_storage_probe,
1406};
1407
1408UCLASS_DRIVER(usb_mass_storage) = {
1409 .id = UCLASS_MASS_STORAGE,
1410 .name = "usb_mass_storage",
1411};
1412
1413static const struct usb_device_id mass_storage_id_table[] = {
1414 {
1415 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1416 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1417 },
1418 { } /* Terminating entry */
1419};
1420
Simon Glassabb59cf2015-07-06 16:47:51 -06001421U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glassacf277a2015-03-25 12:22:16 -06001422
1423#endif