blob: b9784304086ecdc7ec7beaaeedb853af513824de [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>
Christian Eggersc9182612008-05-21 22:12:00 +020042#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000043#include <asm/processor.h>
Simon Glassacf277a2015-03-25 12:22:16 -060044#include <dm/device-internal.h>
wdenkaffae2b2002-08-17 09:36:01 +000045
Grant Likely735dd972007-02-20 09:04:34 +010046#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000047#include <usb.h>
48
wdenk80885a92004-02-26 23:46:20 +000049#undef BBB_COMDAT_TRACE
50#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000051
wdenkaffae2b2002-08-17 09:36:01 +000052#include <scsi.h>
53/* direction table -- this indicates the direction of the data
54 * transfer for each command code -- a 1 indicates input
55 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040056static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000057 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
58 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
61};
62#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
63
Puneet Saxenaf5766132012-04-03 14:56:06 +053064static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010065static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +000066
wdenkaffae2b2002-08-17 09:36:01 +000067#define USB_MAX_STOR_DEV 5
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);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200121unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000122 lbaint_t blkcnt, void *buffer);
Sascha Silbeff8fef52013-06-14 13:07:25 +0200123unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000124 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
Sascha Silbeff8fef52013-06-14 13:07:25 +02001029unsigned long usb_stor_read(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001030 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001031{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001032 lbaint_t start, blks;
1033 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001034 unsigned short smallblks;
1035 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001036 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001037 int retry;
wdenkf8d813e2004-03-02 14:05:39 +00001038 ccb *srb = &usb_ccb;
1039
1040 if (blkcnt == 0)
1041 return 0;
1042
1043 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001045 debug("\nusb_read: dev %d\n", device);
1046 dev = usb_dev_desc[device].priv;
1047 if (!dev) {
1048 debug("%s: No device\n", __func__);
1049 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001050 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001051 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001052
1053 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001054 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001055 buf_addr = (uintptr_t)buffer;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001056 start = blknr;
1057 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001058
Vivek Gautamceb49722013-04-12 16:34:33 +05301059 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001060 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001061
wdenkaffae2b2002-08-17 09:36:01 +00001062 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001063 /* XXX need some comment here */
1064 retry = 2;
1065 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001066 if (blks > USB_MAX_XFER_BLK)
1067 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001068 else
1069 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001070retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001071 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001072 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001073 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1074 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001075 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301076 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001077 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001078 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001079 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001080 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001081 break;
1082 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001083 start += smallblks;
1084 blks -= smallblks;
1085 buf_addr += srb->datalen;
1086 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001087 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001088
Vivek Gautamceb49722013-04-12 16:34:33 +05301089 debug("usb_read: end startblk " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001090 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamceb49722013-04-12 16:34:33 +05301091 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092
wdenkaffae2b2002-08-17 09:36:01 +00001093 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001094 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001095 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001096 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001097}
1098
Sascha Silbeff8fef52013-06-14 13:07:25 +02001099unsigned long usb_stor_write(int device, lbaint_t blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001100 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301101{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001102 lbaint_t start, blks;
1103 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301104 unsigned short smallblks;
1105 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001106 struct us_data *ss;
Simon Glass84073b62015-03-25 12:22:13 -06001107 int retry;
Mahavir Jain127e1082009-11-03 12:22:10 +05301108 ccb *srb = &usb_ccb;
1109
1110 if (blkcnt == 0)
1111 return 0;
1112
1113 device &= 0xff;
1114 /* Setup device */
Simon Glass84073b62015-03-25 12:22:13 -06001115 debug("\nusb_write: dev %d\n", device);
1116 dev = usb_dev_desc[device].priv;
1117 if (!dev)
1118 return 0;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001119 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301120
1121 usb_disable_asynch(1); /* asynch transfer not allowed */
1122
1123 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001124 buf_addr = (uintptr_t)buffer;
Mahavir Jain127e1082009-11-03 12:22:10 +05301125 start = blknr;
1126 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301127
Vivek Gautamceb49722013-04-12 16:34:33 +05301128 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glass4fd074d2014-10-15 04:38:38 -06001129 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301130
1131 do {
1132 /* If write fails retry for max retry count else
1133 * return with number of blocks written successfully.
1134 */
1135 retry = 2;
1136 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001137 if (blks > USB_MAX_XFER_BLK)
1138 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301139 else
1140 smallblks = (unsigned short) blks;
1141retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001142 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301143 usb_show_progress();
1144 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1145 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001146 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301147 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001148 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301149 if (retry--)
1150 goto retry_it;
1151 blkcnt -= blks;
1152 break;
1153 }
1154 start += smallblks;
1155 blks -= smallblks;
1156 buf_addr += srb->datalen;
1157 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001158 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301159
Simon Glass4fd074d2014-10-15 04:38:38 -06001160 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1161 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301162
1163 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001164 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001165 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301166 return blkcnt;
1167
1168}
wdenkaffae2b2002-08-17 09:36:01 +00001169
1170/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001171int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1172 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001173{
Tom Rix8f8bd562009-10-31 12:37:38 -05001174 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001175 int i;
Vivek Gautam605bd752013-04-12 16:34:34 +05301176 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001177 unsigned int flags = 0;
1178
1179 int protocol = 0;
1180 int subclass = 0;
1181
wdenkaffae2b2002-08-17 09:36:01 +00001182 /* let's examine the device now */
1183 iface = &dev->config.if_desc[ifnum];
1184
1185#if 0
1186 /* this is the place to patch some storage devices */
Vivek Gautamceb49722013-04-12 16:34:33 +05301187 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001188 dev->descriptor.idProduct);
1189
1190 if ((dev->descriptor.idVendor) == 0x066b &&
1191 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301192 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001193 protocol = US_PR_CB;
1194 subclass = US_SC_UFI; /* an assumption */
1195 }
1196#endif
1197
1198 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001199 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1200 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1201 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001202 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001203 /* if it's not a mass storage, we go no further */
1204 return 0;
1205 }
1206
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001207 memset(ss, 0, sizeof(struct us_data));
1208
wdenkaffae2b2002-08-17 09:36:01 +00001209 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301210 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001211
1212 /* Initialize the us_data structure with some useful info */
1213 ss->flags = flags;
1214 ss->ifnum = ifnum;
1215 ss->pusb_dev = dev;
1216 ss->attention_done = 0;
1217
1218 /* If the device has subclass and protocol, then use that. Otherwise,
1219 * take data from the specific interface.
1220 */
1221 if (subclass) {
1222 ss->subclass = subclass;
1223 ss->protocol = protocol;
1224 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001225 ss->subclass = iface->desc.bInterfaceSubClass;
1226 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001227 }
1228
1229 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301230 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001231 switch (ss->protocol) {
1232 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301233 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001234 ss->transport = usb_stor_CB_transport;
1235 ss->transport_reset = usb_stor_CB_reset;
1236 break;
1237
1238 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301239 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001240 ss->transport = usb_stor_CB_transport;
1241 ss->transport_reset = usb_stor_CB_reset;
1242 break;
wdenk149dded2003-09-10 18:20:28 +00001243 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301244 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001245 ss->transport = usb_stor_BBB_transport;
1246 ss->transport_reset = usb_stor_BBB_reset;
1247 break;
wdenkaffae2b2002-08-17 09:36:01 +00001248 default:
wdenk80885a92004-02-26 23:46:20 +00001249 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001250 return 0;
1251 break;
1252 }
1253
1254 /*
1255 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1256 * An optional interrupt is OK (necessary for CBI protocol).
1257 * We will ignore any others.
1258 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001259 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301260 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001261 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301262 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001263 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301264 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1265 ss->ep_in = ep_desc->bEndpointAddress &
1266 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001267 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001268 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301269 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001270 USB_ENDPOINT_NUMBER_MASK;
1271 }
1272
1273 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301274 if ((ep_desc->bmAttributes &
1275 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1276 ss->ep_int = ep_desc->bEndpointAddress &
1277 USB_ENDPOINT_NUMBER_MASK;
1278 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001279 }
1280 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301281 debug("Endpoints In %d Out %d Int %d\n",
1282 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001283
1284 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001285 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001286 !ss->ep_in || !ss->ep_out ||
1287 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301288 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001289 return 0;
1290 }
1291 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001292 /* We only handle certain protocols. Currently, these are
1293 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001294 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001295 */
wdenk80885a92004-02-26 23:46:20 +00001296 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1297 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001298 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001299 return 0;
1300 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001301 if (ss->ep_int) {
1302 /* we had found an interrupt endpoint, prepare irq pipe
1303 * set up the IRQ pipe and handler
1304 */
wdenkaffae2b2002-08-17 09:36:01 +00001305 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1306 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1307 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001308 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001309 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001310 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001311 return 1;
1312}
1313
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001314int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1315 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001316{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001317 unsigned char perq, modi;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001318 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1319 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1320 u32 capacity, blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001321 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001322
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001323 pccb->pdata = usb_stor_buf;
1324
1325 dev_desc->target = dev->devnum;
1326 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301327 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001328
Simon Glass1d5827a2015-03-25 12:22:12 -06001329 if (usb_inquiry(pccb, ss)) {
1330 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001331 return -1;
Simon Glass1d5827a2015-03-25 12:22:12 -06001332 }
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001333
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001334 perq = usb_stor_buf[0];
1335 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001336
Soeren Moch6a559bb2014-11-08 07:02:14 +01001337 /*
1338 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1339 * they would not respond to test_unit_ready .
1340 */
1341 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass1d5827a2015-03-25 12:22:12 -06001342 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001343 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001344 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001345 if ((modi&0x80) == 0x80) {
1346 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001347 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001348 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001349 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1350 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1351 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001352 dev_desc->vendor[8] = 0;
1353 dev_desc->product[16] = 0;
1354 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001355#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001356 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1357 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001358#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301359 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1360 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001361 if (usb_test_unit_ready(pccb, ss)) {
1362 printf("Device NOT ready\n"
1363 " Request Sense returned %02X %02X %02X\n",
1364 pccb->sense_buf[2], pccb->sense_buf[12],
1365 pccb->sense_buf[13]);
1366 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001367 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001368 return 1;
1369 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001370 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001371 }
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001372 pccb->pdata = (unsigned char *)cap;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001373 memset(pccb->pdata, 0, 8);
1374 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001375 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001376 cap[0] = 2880;
1377 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001378 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001379 ss->flags &= ~USB_READY;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001380 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001381#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001382 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1383 cap[0] >>= 16;
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001384
Christian Eggersc9182612008-05-21 22:12:00 +02001385 cap[0] = cpu_to_be32(cap[0]);
1386 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001387#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001388
Sergey Temerkhanovf6570872015-04-01 17:18:46 +03001389 capacity = be32_to_cpu(cap[0]) + 1;
1390 blksz = be32_to_cpu(cap[1]);
1391
1392 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1393 dev_desc->lba = capacity;
1394 dev_desc->blksz = blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001395 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001396 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301397 debug(" address %d\n", dev_desc->target);
1398 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001399
1400 init_part(dev_desc);
1401
Vivek Gautamceb49722013-04-12 16:34:33 +05301402 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001403 return 1;
1404}
Simon Glassacf277a2015-03-25 12:22:16 -06001405
1406#ifdef CONFIG_DM_USB
1407
1408static int usb_mass_storage_probe(struct udevice *dev)
1409{
1410 struct usb_device *udev = dev_get_parentdata(dev);
1411 int ret;
1412
1413 usb_disable_asynch(1); /* asynch transfer not allowed */
1414 ret = usb_stor_probe_device(udev);
1415 usb_disable_asynch(0); /* asynch transfer allowed */
1416
1417 return ret;
1418}
1419
1420static const struct udevice_id usb_mass_storage_ids[] = {
1421 { .compatible = "usb-mass-storage" },
1422 { }
1423};
1424
1425U_BOOT_DRIVER(usb_mass_storage) = {
1426 .name = "usb_mass_storage",
1427 .id = UCLASS_MASS_STORAGE,
1428 .of_match = usb_mass_storage_ids,
1429 .probe = usb_mass_storage_probe,
1430};
1431
1432UCLASS_DRIVER(usb_mass_storage) = {
1433 .id = UCLASS_MASS_STORAGE,
1434 .name = "usb_mass_storage",
1435};
1436
1437static const struct usb_device_id mass_storage_id_table[] = {
1438 {
1439 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1440 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1441 },
1442 { } /* Terminating entry */
1443};
1444
Simon Glassabb59cf2015-07-06 16:47:51 -06001445U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glassacf277a2015-03-25 12:22:16 -06001446
1447#endif