blob: 8737cf7ceaabbb673b094ff8237e4c9c3fb9d78b [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
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010068static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000069
70static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
71
72struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010073typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
74typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000075
76struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010077 struct usb_device *pusb_dev; /* this usb_device */
78
79 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +020080# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010081 unsigned char ifnum; /* interface number */
82 unsigned char ep_in; /* in endpoint */
83 unsigned char ep_out; /* out ....... */
84 unsigned char ep_int; /* interrupt . */
85 unsigned char subclass; /* as in overview */
86 unsigned char protocol; /* .............. */
87 unsigned char attention_done; /* force attn on first cmd */
88 unsigned short ip_data; /* interrupt data */
89 int action; /* what to do */
90 int ip_wanted; /* needed */
91 int *irq_handle; /* for USB int requests */
92 unsigned int irqpipe; /* pipe for release_irq */
93 unsigned char irqmaxp; /* max packed for irq Pipe */
94 unsigned char irqinterval; /* Intervall for IRQ Pipe */
95 ccb *srb; /* current srb */
96 trans_reset transport_reset; /* reset routine */
97 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000098};
99
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200100#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000101/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200102 * The U-Boot EHCI driver can handle any transfer length as long as there is
103 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
104 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000105 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200106#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200107#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200108#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200109#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000110
wdenkaffae2b2002-08-17 09:36:01 +0000111static struct us_data usb_stor[USB_MAX_STOR_DEV];
112
wdenk80885a92004-02-26 23:46:20 +0000113#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000114#define USB_STOR_TRANSPORT_FAILED -1
115#define USB_STOR_TRANSPORT_ERROR -2
116
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100117int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
118 block_dev_desc_t *dev_desc);
119int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
120 struct us_data *ss);
Stephen Warren7c4213f2015-12-07 11:38:48 -0700121static unsigned long usb_stor_read(block_dev_desc_t *block_dev, lbaint_t blknr,
122 lbaint_t blkcnt, void *buffer);
123static unsigned long usb_stor_write(block_dev_desc_t *block_dev, lbaint_t blknr,
124 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000125void uhci_show_temp_int_td(void);
126
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000127#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000128block_dev_desc_t *usb_stor_get_dev(int index)
129{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200130 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000131}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000132#endif
wdenkaffae2b2002-08-17 09:36:01 +0000133
Kim Phillips199adb62012-10-29 13:34:32 +0000134static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000135{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200136 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000137}
138
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100139/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200140 * show info on storage devices; 'usb start/init' must be invoked earlier
141 * as we only retrieve structures populated during devices initialization
142 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100143int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200144{
145 int i;
146
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100147 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200148 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100149 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200150 dev_print(&usb_dev_desc[i]);
151 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100152 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100153 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700154
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100155 printf("No storage devices, perhaps not 'usb start'ed..?\n");
156 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200157}
158
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200159static unsigned int usb_get_max_lun(struct us_data *us)
160{
161 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530162 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200163 len = usb_control_msg(us->pusb_dev,
164 usb_rcvctrlpipe(us->pusb_dev, 0),
165 US_BBB_GET_MAX_LUN,
166 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
167 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530168 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200169 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530170 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530171 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200172}
173
Simon Glass91557572015-03-25 12:22:15 -0600174static int usb_stor_probe_device(struct usb_device *dev)
175{
176 if (dev == NULL)
177 return -ENOENT; /* no more devices available */
178
179 debug("\n\nProbing for storage\n");
180 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
181 /* OK, it's a storage device. Iterate over its LUNs
182 * and populate `usb_dev_desc'.
183 */
184 int lun, max_lun, start = usb_max_devs;
185
186 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
187 for (lun = 0;
188 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
189 lun++) {
190 struct block_dev_desc *blkdev;
191
192 blkdev = &usb_dev_desc[usb_max_devs];
193 memset(blkdev, '\0', sizeof(block_dev_desc_t));
194 blkdev->if_type = IF_TYPE_USB;
195 blkdev->dev = usb_max_devs;
196 blkdev->part_type = PART_TYPE_UNKNOWN;
197 blkdev->target = 0xff;
198 blkdev->type = DEV_TYPE_UNKNOWN;
199 blkdev->block_read = usb_stor_read;
200 blkdev->block_write = usb_stor_write;
201 blkdev->lun = lun;
202 blkdev->priv = dev;
203
204 if (usb_stor_get_info(dev, &usb_stor[start],
205 &usb_dev_desc[usb_max_devs]) ==
206 1) {
207 usb_max_devs++;
208 debug("%s: Found device %p\n", __func__, dev);
209 }
210 }
211 }
212
213 /* if storage device */
214 if (usb_max_devs == USB_MAX_STOR_DEV) {
215 printf("max USB Storage Device reached: %d stopping\n",
216 usb_max_devs);
217 return -ENOSPC;
218 }
219
220 return 0;
221}
222
223void usb_stor_reset(void)
224{
225 usb_max_devs = 0;
226}
227
Simon Glassacf277a2015-03-25 12:22:16 -0600228#ifndef CONFIG_DM_USB
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100229/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200230 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000231 * to the user if mode = 1
232 * returns current device or -1 if no
233 */
234int usb_stor_scan(int mode)
235{
Simon Glass7fc2c1e2015-04-16 17:27:34 -0600236 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000237
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100238 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200239 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100240
wdenkaffae2b2002-08-17 09:36:01 +0000241 usb_disable_asynch(1); /* asynch transfer not allowed */
242
Simon Glass91557572015-03-25 12:22:15 -0600243 usb_stor_reset();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glass91557572015-03-25 12:22:15 -0600245 struct usb_device *dev;
246
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100247 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530248 debug("i=%d\n", i);
Simon Glass91557572015-03-25 12:22:15 -0600249 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000250 break;
wdenkaffae2b2002-08-17 09:36:01 +0000251 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200252
wdenkaffae2b2002-08-17 09:36:01 +0000253 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200254 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100255 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000256 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100257 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000258}
Simon Glassacf277a2015-03-25 12:22:16 -0600259#endif
wdenkaffae2b2002-08-17 09:36:01 +0000260
261static int usb_stor_irq(struct usb_device *dev)
262{
263 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100264 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000265
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100266 if (us->ip_wanted)
267 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000268 return 0;
269}
270
271
Vivek Gautamceb49722013-04-12 16:34:33 +0530272#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000273
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100274static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000275{
276 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100277 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
278 for (i = 0; i < 12; i++)
279 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000280 printf("\n");
281}
282
283static void display_int_status(unsigned long tmp)
284{
285 printf("Status: %s %s %s %s %s %s %s\n",
286 (tmp & USB_ST_ACTIVE) ? "Active" : "",
287 (tmp & USB_ST_STALLED) ? "Stalled" : "",
288 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
289 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
290 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
291 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
292 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
293}
294#endif
295/***********************************************************************
296 * Data transfer routines
297 ***********************************************************************/
298
299static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
300{
301 int max_size;
302 int this_xfer;
303 int result;
304 int partial;
305 int maxtry;
306 int stat;
307
308 /* determine the maximum packet size for these transfers */
309 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
310
311 /* while we have data left to transfer */
312 while (length) {
313
314 /* calculate how long this will be -- maximum or a remainder */
315 this_xfer = length > max_size ? max_size : length;
316 length -= this_xfer;
317
318 /* setup the retry counter */
319 maxtry = 10;
320
321 /* set up the transfer loop */
322 do {
323 /* transfer the data */
Simon Glass05108132015-03-25 12:22:14 -0600324 debug("Bulk xfer 0x%lx(%d) try #%d\n",
325 (ulong)map_to_sysmem(buf), this_xfer,
326 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000327 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100328 this_xfer, &partial,
329 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530330 debug("bulk_msg returned %d xferred %d/%d\n",
331 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100332 if (us->pusb_dev->status != 0) {
333 /* if we stall, we need to clear it before
334 * we go on
335 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530336#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000337 display_int_status(us->pusb_dev->status);
338#endif
339 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530340 debug("stalled ->clearing endpoint" \
341 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000342 stat = us->pusb_dev->status;
343 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100344 us->pusb_dev->status = stat;
345 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530346 debug("bulk transferred" \
347 "with error %lX," \
348 " but data ok\n",
349 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000350 return 0;
351 }
352 else
353 return result;
354 }
355 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530356 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000357 return result;
358 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530359 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100360 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530361 debug(" %ld, but data ok\n",
362 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000363 return 0;
364 }
365 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530366 debug(" %ld, data %d\n",
367 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000368 if (!maxtry--)
369 return result;
370 }
371 /* update to show what data was transferred */
372 this_xfer -= partial;
373 buf += partial;
374 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100375 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000376 }
377
378 /* if we get here, we're done and successful */
379 return 0;
380}
381
wdenk149dded2003-09-10 18:20:28 +0000382static int usb_stor_BBB_reset(struct us_data *us)
383{
384 int result;
385 unsigned int pipe;
386
387 /*
388 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
389 *
390 * For Reset Recovery the host shall issue in the following order:
391 * a) a Bulk-Only Mass Storage Reset
392 * b) a Clear Feature HALT to the Bulk-In endpoint
393 * c) a Clear Feature HALT to the Bulk-Out endpoint
394 *
395 * This is done in 3 steps.
396 *
397 * If the reset doesn't succeed, the device should be port reset.
398 *
399 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
400 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530401 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100402 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
403 US_BBB_RESET,
404 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000405 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200406
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100407 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530408 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000409 return -1;
410 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200411
wdenk149dded2003-09-10 18:20:28 +0000412 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000413 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530414 debug("BBB_reset result %d: status %lX reset\n",
415 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000416 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
417 result = usb_clear_halt(us->pusb_dev, pipe);
418 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000419 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530420 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
421 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000422 /* long wait for reset */
423 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
424 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000425 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530426 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
427 result, us->pusb_dev->status);
428 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000429 return 0;
430}
431
wdenkaffae2b2002-08-17 09:36:01 +0000432/* FIXME: this reset function doesn't really reset the port, and it
433 * should. Actually it should probably do what it's doing here, and
434 * reset the port physically
435 */
436static int usb_stor_CB_reset(struct us_data *us)
437{
438 unsigned char cmd[12];
439 int result;
440
Vivek Gautamceb49722013-04-12 16:34:33 +0530441 debug("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100442 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000443 cmd[0] = SCSI_SEND_DIAG;
444 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100445 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
446 US_CBI_ADSC,
447 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
448 0, us->ifnum, cmd, sizeof(cmd),
449 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000450
451 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000452 mdelay(1500);
Vivek Gautamceb49722013-04-12 16:34:33 +0530453 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
454 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000455 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
456 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
457
Vivek Gautamceb49722013-04-12 16:34:33 +0530458 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000459 return 0;
460}
461
wdenk149dded2003-09-10 18:20:28 +0000462/*
463 * Set up the command for a BBB device. Note that the actual SCSI
464 * command is copied into cbw.CBWCDB.
465 */
Kim Phillips199adb62012-10-29 13:34:32 +0000466static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000467{
468 int result;
469 int actlen;
470 int dir_in;
471 unsigned int pipe;
Simon Glass2e17c872015-03-25 12:22:11 -0600472 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000473
474 dir_in = US_DIRECTION(srb->cmd[0]);
475
476#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530477 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100478 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
479 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000480 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100481 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000482 printf("cmd[%d] %#x ", result, srb->cmd[result]);
483 printf("\n");
484 }
485#endif
486 /* sanity checks */
487 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530488 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000489 return -1;
490 }
491
492 /* always OUT to the ep */
493 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
494
Puneet Saxenaf5766132012-04-03 14:56:06 +0530495 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
496 cbw->dCBWTag = cpu_to_le32(CBWTag++);
497 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
498 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
499 cbw->bCBWLUN = srb->lun;
500 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000501 /* copy the command data into the CBW command data buffer */
502 /* DST SRC LEN!!! */
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300503
Puneet Saxenaf5766132012-04-03 14:56:06 +0530504 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
505 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100506 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000507 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530508 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000509 return result;
510}
511
wdenkaffae2b2002-08-17 09:36:01 +0000512/* FIXME: we also need a CBI_command which sets up the completion
513 * interrupt, and waits for it
514 */
Kim Phillips199adb62012-10-29 13:34:32 +0000515static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000516{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200517 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100518 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000519 unsigned int pipe;
520 unsigned long status;
521
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100522 retry = 5;
523 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000524
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100525 if (dir_in)
526 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
527 else
528 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
529
530 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530531 debug("CBI gets a command: Try %d\n", 5 - retry);
532#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000533 usb_show_srb(srb);
534#endif
535 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100536 result = usb_control_msg(us->pusb_dev,
537 usb_sndctrlpipe(us->pusb_dev , 0),
538 US_CBI_ADSC,
539 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000540 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100541 srb->cmd, srb->cmdlen,
542 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530543 debug("CB_transport: control msg returned %d, status %lX\n",
544 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000545 /* check the return code for the command */
546 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 if (us->pusb_dev->status & USB_ST_STALLED) {
548 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530549 debug(" stall during command found," \
550 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100551 usb_clear_halt(us->pusb_dev,
552 usb_sndctrlpipe(us->pusb_dev, 0));
553 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000554 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530555 debug(" error during command %02X" \
556 " Stat = %lX\n", srb->cmd[0],
557 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000558 return result;
559 }
560 /* transfer the data payload for this command, if one exists*/
561
Vivek Gautamceb49722013-04-12 16:34:33 +0530562 debug("CB_transport: control msg returned %d," \
563 " direction is %s to go 0x%lx\n", result,
564 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000565 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100566 result = us_one_transfer(us, pipe, (char *)srb->pdata,
567 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530568 debug("CBI attempted to transfer data," \
569 " result is %d status %lX, len %d\n",
570 result, us->pusb_dev->status,
571 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100572 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000573 break;
574 } /* if (srb->datalen) */
575 else
576 break;
577 }
578 /* return result */
579
580 return result;
581}
582
583
Kim Phillips199adb62012-10-29 13:34:32 +0000584static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000585{
586 int timeout;
587
wdenk80885a92004-02-26 23:46:20 +0000588 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100589 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000590 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
591 timeout = 1000;
592 while (timeout--) {
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300593 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000594 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000595 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000596 }
597 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100598 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000599 us->ip_wanted = 0;
600 return USB_STOR_TRANSPORT_ERROR;
601 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530602 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
603 us->ip_data, us->pusb_dev->irq_act_len,
604 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000605 /* UFI gives us ASC and ASCQ, like a request sense */
606 if (us->subclass == US_SC_UFI) {
607 if (srb->cmd[0] == SCSI_REQ_SENSE ||
608 srb->cmd[0] == SCSI_INQUIRY)
609 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000610 else if (us->ip_data)
611 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000612 else
wdenk80885a92004-02-26 23:46:20 +0000613 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000614 }
615 /* otherwise, we interpret the data normally */
616 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000617 case 0x0001:
618 return USB_STOR_TRANSPORT_GOOD;
619 case 0x0002:
620 return USB_STOR_TRANSPORT_FAILED;
621 default:
622 return USB_STOR_TRANSPORT_ERROR;
623 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000624 return USB_STOR_TRANSPORT_ERROR;
625}
626
627#define USB_TRANSPORT_UNKNOWN_RETRY 5
628#define USB_TRANSPORT_NOT_READY_RETRY 10
629
wdenk149dded2003-09-10 18:20:28 +0000630/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000631static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000632{
633 int result;
634
635 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100636 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000637 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000638 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000639 return result;
640}
641
Kim Phillips199adb62012-10-29 13:34:32 +0000642static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000643{
644 int result, retry;
645 int dir_in;
646 int actlen, data_actlen;
647 unsigned int pipe, pipein, pipeout;
Simon Glass2e17c872015-03-25 12:22:11 -0600648 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000649#ifdef BBB_XPORT_TRACE
650 unsigned char *ptr;
651 int index;
652#endif
653
654 dir_in = US_DIRECTION(srb->cmd[0]);
655
656 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530657 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000658 result = usb_stor_BBB_comdat(srb, us);
659 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530660 debug("failed to send CBW status %ld\n",
661 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000662 usb_stor_BBB_reset(us);
663 return USB_STOR_TRANSPORT_FAILED;
664 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200665 if (!(us->flags & USB_READY))
666 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000667 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
668 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
669 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000670 data_actlen = 0;
671 /* no data, go immediately to the STATUS phase */
672 if (srb->datalen == 0)
673 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530674 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000675 if (dir_in)
676 pipe = pipein;
677 else
678 pipe = pipeout;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +0300679
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100680 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
681 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000682 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100683 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530684 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000685 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100686 result = usb_stor_BBB_clear_endpt_stall(us,
687 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000688 if (result >= 0)
689 /* continue on to STATUS phase */
690 goto st;
691 }
692 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530693 debug("usb_bulk_msg error status %ld\n",
694 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000695 usb_stor_BBB_reset(us);
696 return USB_STOR_TRANSPORT_FAILED;
697 }
698#ifdef BBB_XPORT_TRACE
699 for (index = 0; index < data_actlen; index++)
700 printf("pdata[%d] %#x ", index, srb->pdata[index]);
701 printf("\n");
702#endif
703 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100704st:
wdenk149dded2003-09-10 18:20:28 +0000705 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100706again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530707 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530708 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200709 &actlen, USB_CNTL_TIMEOUT*5);
710
wdenk149dded2003-09-10 18:20:28 +0000711 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100712 if ((result < 0) && (retry < 1) &&
713 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530714 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000715 /* clear the STALL on the endpoint */
716 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
717 if (result >= 0 && (retry++ < 1))
718 /* do a retry */
719 goto again;
720 }
721 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530722 debug("usb_bulk_msg error status %ld\n",
723 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000724 usb_stor_BBB_reset(us);
725 return USB_STOR_TRANSPORT_FAILED;
726 }
727#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530728 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000729 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
730 printf("ptr[%d] %#x ", index, ptr[index]);
731 printf("\n");
732#endif
733 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530734 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000735 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
736 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530737 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530738 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000739 usb_stor_BBB_reset(us);
740 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530741 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530742 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000743 usb_stor_BBB_reset(us);
744 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530745 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530746 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000747 usb_stor_BBB_reset(us);
748 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530749 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530750 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000751 usb_stor_BBB_reset(us);
752 return USB_STOR_TRANSPORT_FAILED;
753 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530754 debug("transferred %dB instead of %ldB\n",
755 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000756 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530757 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530758 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000759 return USB_STOR_TRANSPORT_FAILED;
760 }
761
762 return result;
763}
764
Kim Phillips199adb62012-10-29 13:34:32 +0000765static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000766{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100767 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000768 ccb *psrb;
769 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100770 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000771
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200772 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100773 status = USB_STOR_TRANSPORT_GOOD;
774 retry = 0;
775 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000776 /* issue the command */
777do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100778 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530779 debug("command / Data returned %d, status %lX\n",
780 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000781 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100782 if (us->protocol == US_PR_CBI) {
783 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000784 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100785 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530786 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000787 return status;
788 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100789 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
790 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
791 if (!us->ip_data) {
792 /* if the status is good, report it */
793 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530794 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000795 return status;
796 }
797 }
798 }
799 /* do we have to issue an auto request? */
800 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100801 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530802 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000803 us->transport_reset(us);
804 return USB_STOR_TRANSPORT_ERROR;
805 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 if ((us->protocol == US_PR_CBI) &&
807 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
808 (srb->cmd[0] == SCSI_INQUIRY))) {
809 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530810 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000811 return USB_STOR_TRANSPORT_GOOD;
812 }
813 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100814 memset(&psrb->cmd[0], 0, 12);
815 psrb->cmd[0] = SCSI_REQ_SENSE;
816 psrb->cmd[1] = srb->lun << 5;
817 psrb->cmd[4] = 18;
818 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200819 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100820 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000821 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100822 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530823 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000824 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100825 if (us->protocol == US_PR_CBI)
826 status = usb_stor_CBI_get_status(psrb, us);
827
828 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530829 debug(" AUTO REQUEST ERROR %ld\n",
830 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000831 return USB_STOR_TRANSPORT_ERROR;
832 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530833 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
834 srb->sense_buf[0], srb->sense_buf[2],
835 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000836 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100837 if ((srb->sense_buf[2] == 0) &&
838 (srb->sense_buf[12] == 0) &&
839 (srb->sense_buf[13] == 0)) {
840 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000841 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100842 }
843
wdenkaffae2b2002-08-17 09:36:01 +0000844 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 switch (srb->sense_buf[2]) {
846 case 0x01:
847 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000848 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000849 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 case 0x02:
851 /* Not Ready */
852 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
853 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
854 " 0x%02X (NOT READY)\n", srb->cmd[0],
855 srb->sense_buf[0], srb->sense_buf[2],
856 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000857 return USB_STOR_TRANSPORT_FAILED;
858 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000859 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000860 goto do_retry;
861 }
862 break;
863 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100864 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
865 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
866 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
867 srb->sense_buf[2], srb->sense_buf[12],
868 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000869 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 } else
wdenk149dded2003-09-10 18:20:28 +0000871 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000872 break;
wdenkaffae2b2002-08-17 09:36:01 +0000873 }
874 return USB_STOR_TRANSPORT_FAILED;
875}
876
877
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000879{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100880 int retry, i;
881 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000882 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100883 memset(&srb->cmd[0], 0, 12);
884 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200885 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100886 srb->cmd[4] = 36;
887 srb->datalen = 36;
888 srb->cmdlen = 12;
889 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530890 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100891 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000892 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200893 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000894
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100895 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000896 printf("error in inquiry\n");
897 return -1;
898 }
899 return 0;
900}
901
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100902static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000903{
904 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000905
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906 ptr = (char *)srb->pdata;
907 memset(&srb->cmd[0], 0, 12);
908 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200909 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100910 srb->cmd[4] = 18;
911 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200912 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100913 srb->cmdlen = 12;
914 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530915 debug("Request Sense returned %02X %02X %02X\n",
916 srb->sense_buf[2], srb->sense_buf[12],
917 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100918 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000919 return 0;
920}
921
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100922static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000923{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200924 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000925
wdenkaffae2b2002-08-17 09:36:01 +0000926 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100927 memset(&srb->cmd[0], 0, 12);
928 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200929 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100930 srb->datalen = 0;
931 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200932 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
933 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000934 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200935 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100936 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800937 /*
938 * Check the Key Code Qualifier, if it matches
939 * "Not Ready - medium not present"
940 * (the sense Key equals 0x2 and the ASC is 0x3a)
941 * return immediately as the medium being absent won't change
942 * unless there is a user action.
943 */
944 if ((srb->sense_buf[2] == 0x02) &&
945 (srb->sense_buf[12] == 0x3a))
946 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000947 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100948 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000949
wdenkaffae2b2002-08-17 09:36:01 +0000950 return -1;
951}
952
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100953static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000954{
955 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100956 /* XXX retries */
957 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000958 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100959 memset(&srb->cmd[0], 0, 12);
960 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200961 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100962 srb->datalen = 8;
963 srb->cmdlen = 12;
964 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000965 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100966 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000967
wdenkaffae2b2002-08-17 09:36:01 +0000968 return -1;
969}
970
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100971static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
972 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000973{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100974 memset(&srb->cmd[0], 0, 12);
975 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200976 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100977 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
978 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
979 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
980 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
981 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
982 srb->cmd[8] = (unsigned char) blocks & 0xff;
983 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +0530984 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100985 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000986}
987
Mahavir Jain127e1082009-11-03 12:22:10 +0530988static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
989 unsigned short blocks)
990{
991 memset(&srb->cmd[0], 0, 12);
992 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200993 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +0530994 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
995 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
996 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
997 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
998 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
999 srb->cmd[8] = (unsigned char) blocks & 0xff;
1000 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301001 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301002 return ss->transport(srb, ss);
1003}
1004
wdenkaffae2b2002-08-17 09:36:01 +00001005
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001006#ifdef CONFIG_USB_BIN_FIXUP
1007/*
1008 * Some USB storage devices queried for SCSI identification data respond with
1009 * binary strings, which if output to the console freeze the terminal. The
1010 * workaround is to modify the vendor and product strings read from such
1011 * device with proper values (as reported by 'usb info').
1012 *
1013 * Vendor and product length limits are taken from the definition of
1014 * block_dev_desc_t in include/part.h.
1015 */
1016static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1017 unsigned char vendor[],
1018 unsigned char product[]) {
1019 const unsigned char max_vendor_len = 40;
1020 const unsigned char max_product_len = 20;
1021 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001022 strncpy((char *)vendor, "SMSC", max_vendor_len);
1023 strncpy((char *)product, "Flash Media Cntrller",
1024 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001025 }
1026}
1027#endif /* CONFIG_USB_BIN_FIXUP */
1028
Stephen Warren7c4213f2015-12-07 11:38:48 -07001029static unsigned long usb_stor_read(block_dev_desc_t *block_dev, lbaint_t blknr,
1030 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001031{
Stephen Warren7c4213f2015-12-07 11:38:48 -07001032 int device = block_dev->dev;
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
Stephen Warren7c4213f2015-12-07 11:38:48 -07001100static unsigned long usb_stor_write(block_dev_desc_t *block_dev, lbaint_t blknr,
1101 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301102{
Stephen Warren7c4213f2015-12-07 11:38:48 -07001103 int device = block_dev->dev;
Gabe Blacke81e79e2012-10-12 14:26:07 +00001104 lbaint_t start, blks;
1105 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301106 unsigned short smallblks;
1107 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001108 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001109 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301110 ccb *srb = &usb_ccb;
1111
1112 if (blkcnt == 0)
1113 return 0;
1114
1115 device &= 0xff;
1116 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001117 debug("\nusb_write: dev %d\n", device);
1118 dev = usb_dev_desc[device].priv;
1119 if (!dev)
1120 return 0;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001121 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301122
1123 usb_disable_asynch(1); /* asynch transfer not allowed */
1124
1125 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001126 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301127 start = blknr;
1128 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301129
Vivek Gautamceb49722013-04-12 16:34:33 +05301130 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001131 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301132
1133 do {
1134 /* If write fails retry for max retry count else
1135 * return with number of blocks written successfully.
1136 */
1137 retry = 2;
1138 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001139 if (blks > USB_MAX_XFER_BLK)
1140 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301141 else
1142 smallblks = (unsigned short) blks;
1143retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001144 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301145 usb_show_progress();
1146 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1147 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001148 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301149 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001150 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301151 if (retry--)
1152 goto retry_it;
1153 blkcnt -= blks;
1154 break;
1155 }
1156 start += smallblks;
1157 blks -= smallblks;
1158 buf_addr += srb->datalen;
1159 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001160 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301161
Simon Glass4fd074d2014-10-15 04:38:38 -06001162 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1163 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301164
1165 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001166 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001167 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301168 return blkcnt;
1169
1170}
wdenkaffae2b2002-08-17 09:36:01 +00001171
1172/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001173int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1174 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001175{
Tom Rix8f8bd562009-10-31 12:37:38 -05001176 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001177 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301178 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001179 unsigned int flags = 0;
1180
wdenkaffae2b2002-08-17 09:36:01 +00001181 /* let's examine the device now */
1182 iface = &dev->config.if_desc[ifnum];
1183
wdenkaffae2b2002-08-17 09:36:01 +00001184 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001185 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1186 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1187 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001188 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001189 /* if it's not a mass storage, we go no further */
1190 return 0;
1191 }
1192
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001193 memset(ss, 0, sizeof(struct us_data));
1194
wdenkaffae2b2002-08-17 09:36:01 +00001195 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301196 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001197
1198 /* Initialize the us_data structure with some useful info */
1199 ss->flags = flags;
1200 ss->ifnum = ifnum;
1201 ss->pusb_dev = dev;
1202 ss->attention_done = 0;
Tom Rinif5fb78a2015-10-11 07:26:27 -04001203 ss->subclass = iface->desc.bInterfaceSubClass;
1204 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001205
1206 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301207 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001208 switch (ss->protocol) {
1209 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301210 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001211 ss->transport = usb_stor_CB_transport;
1212 ss->transport_reset = usb_stor_CB_reset;
1213 break;
1214
1215 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301216 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001217 ss->transport = usb_stor_CB_transport;
1218 ss->transport_reset = usb_stor_CB_reset;
1219 break;
wdenk149dded2003-09-10 18:20:28 +00001220 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301221 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001222 ss->transport = usb_stor_BBB_transport;
1223 ss->transport_reset = usb_stor_BBB_reset;
1224 break;
wdenkaffae2b2002-08-17 09:36:01 +00001225 default:
wdenk80885a92004-02-26 23:46:20 +00001226 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001227 return 0;
1228 break;
1229 }
1230
1231 /*
1232 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1233 * An optional interrupt is OK (necessary for CBI protocol).
1234 * We will ignore any others.
1235 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001236 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301237 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001238 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301239 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001240 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301241 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1242 ss->ep_in = ep_desc->bEndpointAddress &
1243 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001244 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001245 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301246 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001247 USB_ENDPOINT_NUMBER_MASK;
1248 }
1249
1250 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301251 if ((ep_desc->bmAttributes &
1252 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1253 ss->ep_int = ep_desc->bEndpointAddress &
1254 USB_ENDPOINT_NUMBER_MASK;
1255 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001256 }
1257 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301258 debug("Endpoints In %d Out %d Int %d\n",
1259 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001260
1261 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001262 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001263 !ss->ep_in || !ss->ep_out ||
1264 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301265 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001266 return 0;
1267 }
1268 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001269 /* We only handle certain protocols. Currently, these are
1270 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001271 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001272 */
wdenk80885a92004-02-26 23:46:20 +00001273 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1274 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001275 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001276 return 0;
1277 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001278 if (ss->ep_int) {
1279 /* we had found an interrupt endpoint, prepare irq pipe
1280 * set up the IRQ pipe and handler
1281 */
wdenkaffae2b2002-08-17 09:36:01 +00001282 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1283 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1284 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001285 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001286 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001287 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001288 return 1;
1289}
1290
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001291int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1292 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001293{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001294 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001295 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1296 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1297 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001298 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001299
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001300 pccb->pdata = usb_stor_buf;
1301
1302 dev_desc->target = dev->devnum;
1303 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301304 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001305
Simon Glass1d5827a2015-03-25 12:22:12 -06001306 if (usb_inquiry(pccb, ss)) {
1307 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001308 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001309 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001310
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001311 perq = usb_stor_buf[0];
1312 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001313
Soeren Moch6a559bb2014-11-08 07:02:14 +01001314 /*
1315 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1316 * they would not respond to test_unit_ready .
1317 */
1318 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001319 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001320 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001321 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001322 if ((modi&0x80) == 0x80) {
1323 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001324 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001325 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001326 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1327 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1328 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001329 dev_desc->vendor[8] = 0;
1330 dev_desc->product[16] = 0;
1331 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001332#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001333 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1334 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001335#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301336 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1337 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001338 if (usb_test_unit_ready(pccb, ss)) {
1339 printf("Device NOT ready\n"
1340 " Request Sense returned %02X %02X %02X\n",
1341 pccb->sense_buf[2], pccb->sense_buf[12],
1342 pccb->sense_buf[13]);
1343 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001344 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001345 return 1;
1346 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001347 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001348 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001349 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001350 memset(pccb->pdata, 0, 8);
1351 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001352 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001353 cap[0] = 2880;
1354 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001355 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001356 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001357 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001358#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001359 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1360 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001361
Christian Eggersc9182612008-05-21 22:12:00 +02001362 cap[0] = cpu_to_be32(cap[0]);
1363 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001364#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001365
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001366 capacity = be32_to_cpu(cap[0]) + 1;
1367 blksz = be32_to_cpu(cap[1]);
1368
1369 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1370 dev_desc->lba = capacity;
1371 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001372 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001373 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301374 debug(" address %d\n", dev_desc->target);
1375 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001376
1377 init_part(dev_desc);
1378
Vivek Gautamceb49722013-04-12 16:34:33 +05301379 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001380 return 1;
1381}
Simon Glassacf277a2015-03-25 12:22:16 -06001382
1383#ifdef CONFIG_DM_USB
1384
1385static int usb_mass_storage_probe(struct udevice *dev)
1386{
Simon Glassbcbe3d12015-09-28 23:32:01 -06001387 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassacf277a2015-03-25 12:22:16 -06001388 int ret;
1389
1390 usb_disable_asynch(1); /* asynch transfer not allowed */
1391 ret = usb_stor_probe_device(udev);
1392 usb_disable_asynch(0); /* asynch transfer allowed */
1393
1394 return ret;
1395}
1396
1397static const struct udevice_id usb_mass_storage_ids[] = {
1398 { .compatible = "usb-mass-storage" },
1399 { }
1400};
1401
1402U_BOOT_DRIVER(usb_mass_storage) = {
1403 .name = "usb_mass_storage",
1404 .id = UCLASS_MASS_STORAGE,
1405 .of_match = usb_mass_storage_ids,
1406 .probe = usb_mass_storage_probe,
1407};
1408
1409UCLASS_DRIVER(usb_mass_storage) = {
1410 .id = UCLASS_MASS_STORAGE,
1411 .name = "usb_mass_storage",
1412};
1413
1414static const struct usb_device_id mass_storage_id_table[] = {
1415 {
1416 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1417 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1418 },
1419 { } /* Terminating entry */
1420};
1421
Simon Glassabb59cf2015-07-06 16:47:51 -06001422U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glassacf277a2015-03-25 12:22:16 -06001423
1424#endif