blob: 4fdb55f9faf9061f730abb02710094aed2f5f547 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk6a3d6b02005-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 Glassac9774e2015-03-25 12:22:16 -060012 * Driver model conversion:
13 * (C) Copyright 2015 Google, Inc
wdenkaffae2b2002-08-17 09:36:01 +000014 *
wdenkde887eb2003-09-10 18:20:28 +000015 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020016 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000017 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020018 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-09-10 18:20:28 +000019 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000020 *
Wolfgang Denkd79de1d2013-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 */
wdenkde887eb2003-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.
wdenkde887eb2003-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 Glassac9774e2015-03-25 12:22:16 -060038#include <dm.h>
Simon Glassdf7d34f2015-03-25 12:22:15 -060039#include <errno.h>
Simon Glassb43f7682014-10-15 04:38:38 -060040#include <inttypes.h>
Simon Glass332a9b62015-03-25 12:22:14 -060041#include <mapmem.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060042#include <memalign.h>
Christian Eggers4e0e8d02008-05-21 22:12:00 +020043#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000044#include <asm/processor.h>
Simon Glassac9774e2015-03-25 12:22:16 -060045#include <dm/device-internal.h>
wdenkaffae2b2002-08-17 09:36:01 +000046
Grant Likelyffc2dd72007-02-20 09:04:34 +010047#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000048#include <usb.h>
49
wdenk5f495752004-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 Frysinger165522b2010-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 Saxena6c9bb602012-04-03 14:56:06 +053065static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
Michael Trimarchi956a4352008-12-10 15:52:06 +010066static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +000067
Simon Glass1dae4942016-01-03 13:50:30 -070068#define USB_MAX_STOR_DEV 7
Michael Trimarchi956a4352008-12-10 15:52:06 +010069static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +000070
71static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
72
73struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +010074typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
75typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +000076
77struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +010078 struct usb_device *pusb_dev; /* this usb_device */
79
80 unsigned int flags; /* from filter initially */
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +020081# define USB_READY (1 << 0)
Michael Trimarchi956a4352008-12-10 15:52:06 +010082 unsigned char ifnum; /* interface number */
83 unsigned char ep_in; /* in endpoint */
84 unsigned char ep_out; /* out ....... */
85 unsigned char ep_int; /* interrupt . */
86 unsigned char subclass; /* as in overview */
87 unsigned char protocol; /* .............. */
88 unsigned char attention_done; /* force attn on first cmd */
89 unsigned short ip_data; /* interrupt data */
90 int action; /* what to do */
91 int ip_wanted; /* needed */
92 int *irq_handle; /* for USB int requests */
93 unsigned int irqpipe; /* pipe for release_irq */
94 unsigned char irqmaxp; /* max packed for irq Pipe */
95 unsigned char irqinterval; /* Intervall for IRQ Pipe */
96 ccb *srb; /* current srb */
97 trans_reset transport_reset; /* reset routine */
98 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +000099};
100
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200101#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000102/*
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200103 * The U-Boot EHCI driver can handle any transfer length as long as there is
104 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
105 * limited to 65535 blocks.
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000106 */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200107#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200108#else
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +0200109#define USB_MAX_XFER_BLK 20
Benoît Thébaudeau938051f2012-08-10 18:26:50 +0200110#endif
Stefan Herbrechtsmeier77f385a2012-07-09 09:52:29 +0000111
wdenkaffae2b2002-08-17 09:36:01 +0000112static struct us_data usb_stor[USB_MAX_STOR_DEV];
113
wdenk5f495752004-02-26 23:46:20 +0000114#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000115#define USB_STOR_TRANSPORT_FAILED -1
116#define USB_STOR_TRANSPORT_ERROR -2
117
Michael Trimarchi956a4352008-12-10 15:52:06 +0100118int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
119 block_dev_desc_t *dev_desc);
120int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
121 struct us_data *ss);
Stephen Warrene73f2962015-12-07 11:38:48 -0700122static unsigned long usb_stor_read(block_dev_desc_t *block_dev, lbaint_t blknr,
123 lbaint_t blkcnt, void *buffer);
124static unsigned long usb_stor_write(block_dev_desc_t *block_dev, lbaint_t blknr,
125 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000126void uhci_show_temp_int_td(void);
127
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000128#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000129block_dev_desc_t *usb_stor_get_dev(int index)
130{
Kim B. Heino300ea512010-03-12 15:46:56 +0200131 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000132}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000133#endif
wdenkaffae2b2002-08-17 09:36:01 +0000134
Kim Phillipsb052b602012-10-29 13:34:32 +0000135static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000136{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200137 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000138}
139
Michael Trimarchi956a4352008-12-10 15:52:06 +0100140/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200141 * show info on storage devices; 'usb start/init' must be invoked earlier
142 * as we only retrieve structures populated during devices initialization
143 */
Aras Vaichas7ede1862008-03-25 12:09:07 +1100144int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200145{
146 int i;
147
Aras Vaichas7ede1862008-03-25 12:09:07 +1100148 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200149 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100150 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200151 dev_print(&usb_dev_desc[i]);
152 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100153 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100154 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700155
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100156 printf("No storage devices, perhaps not 'usb start'ed..?\n");
157 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200158}
159
Ludovic Courtès134396c2010-10-05 22:04:26 +0200160static unsigned int usb_get_max_lun(struct us_data *us)
161{
162 int len;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530163 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès134396c2010-10-05 22:04:26 +0200164 len = usb_control_msg(us->pusb_dev,
165 usb_rcvctrlpipe(us->pusb_dev, 0),
166 US_BBB_GET_MAX_LUN,
167 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
168 0, us->ifnum,
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530169 result, sizeof(char),
Ludovic Courtès134396c2010-10-05 22:04:26 +0200170 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530171 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530172 return (len > 0) ? *result : 0;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200173}
174
Simon Glassdf7d34f2015-03-25 12:22:15 -0600175static int usb_stor_probe_device(struct usb_device *dev)
176{
177 if (dev == NULL)
178 return -ENOENT; /* no more devices available */
179
180 debug("\n\nProbing for storage\n");
181 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
182 /* OK, it's a storage device. Iterate over its LUNs
183 * and populate `usb_dev_desc'.
184 */
185 int lun, max_lun, start = usb_max_devs;
186
187 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
188 for (lun = 0;
189 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
190 lun++) {
191 struct block_dev_desc *blkdev;
192
193 blkdev = &usb_dev_desc[usb_max_devs];
194 memset(blkdev, '\0', sizeof(block_dev_desc_t));
195 blkdev->if_type = IF_TYPE_USB;
196 blkdev->dev = usb_max_devs;
197 blkdev->part_type = PART_TYPE_UNKNOWN;
198 blkdev->target = 0xff;
199 blkdev->type = DEV_TYPE_UNKNOWN;
200 blkdev->block_read = usb_stor_read;
201 blkdev->block_write = usb_stor_write;
202 blkdev->lun = lun;
203 blkdev->priv = dev;
204
205 if (usb_stor_get_info(dev, &usb_stor[start],
206 &usb_dev_desc[usb_max_devs]) ==
207 1) {
208 usb_max_devs++;
209 debug("%s: Found device %p\n", __func__, dev);
210 }
211 }
212 }
213
214 /* if storage device */
215 if (usb_max_devs == USB_MAX_STOR_DEV) {
216 printf("max USB Storage Device reached: %d stopping\n",
217 usb_max_devs);
218 return -ENOSPC;
219 }
220
221 return 0;
222}
223
224void usb_stor_reset(void)
225{
226 usb_max_devs = 0;
227}
228
Simon Glassac9774e2015-03-25 12:22:16 -0600229#ifndef CONFIG_DM_USB
Michael Trimarchi956a4352008-12-10 15:52:06 +0100230/*******************************************************************************
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200231 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000232 * to the user if mode = 1
233 * returns current device or -1 if no
234 */
235int usb_stor_scan(int mode)
236{
Simon Glass0f50b162015-04-16 17:27:34 -0600237 unsigned char i;
wdenkaffae2b2002-08-17 09:36:01 +0000238
Michael Trimarchi956a4352008-12-10 15:52:06 +0100239 if (mode == 1)
Lucas Stache6d33452012-09-26 00:14:36 +0200240 printf(" scanning usb for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100241
wdenkaffae2b2002-08-17 09:36:01 +0000242 usb_disable_asynch(1); /* asynch transfer not allowed */
243
Simon Glassdf7d34f2015-03-25 12:22:15 -0600244 usb_stor_reset();
Michael Trimarchi956a4352008-12-10 15:52:06 +0100245 for (i = 0; i < USB_MAX_DEVICE; i++) {
Simon Glassdf7d34f2015-03-25 12:22:15 -0600246 struct usb_device *dev;
247
Michael Trimarchi956a4352008-12-10 15:52:06 +0100248 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530249 debug("i=%d\n", i);
Simon Glassdf7d34f2015-03-25 12:22:15 -0600250 if (usb_stor_probe_device(dev))
wdenkaffae2b2002-08-17 09:36:01 +0000251 break;
wdenkaffae2b2002-08-17 09:36:01 +0000252 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200253
wdenkaffae2b2002-08-17 09:36:01 +0000254 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200255 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100256 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000257 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100258 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000259}
Simon Glassac9774e2015-03-25 12:22:16 -0600260#endif
wdenkaffae2b2002-08-17 09:36:01 +0000261
262static int usb_stor_irq(struct usb_device *dev)
263{
264 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100265 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000266
Michael Trimarchi956a4352008-12-10 15:52:06 +0100267 if (us->ip_wanted)
268 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000269 return 0;
270}
271
272
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530273#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000274
Michael Trimarchi956a4352008-12-10 15:52:06 +0100275static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000276{
277 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100278 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
279 for (i = 0; i < 12; i++)
280 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000281 printf("\n");
282}
283
284static void display_int_status(unsigned long tmp)
285{
286 printf("Status: %s %s %s %s %s %s %s\n",
287 (tmp & USB_ST_ACTIVE) ? "Active" : "",
288 (tmp & USB_ST_STALLED) ? "Stalled" : "",
289 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
290 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
291 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
292 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
293 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
294}
295#endif
296/***********************************************************************
297 * Data transfer routines
298 ***********************************************************************/
299
300static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
301{
302 int max_size;
303 int this_xfer;
304 int result;
305 int partial;
306 int maxtry;
307 int stat;
308
309 /* determine the maximum packet size for these transfers */
310 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
311
312 /* while we have data left to transfer */
313 while (length) {
314
315 /* calculate how long this will be -- maximum or a remainder */
316 this_xfer = length > max_size ? max_size : length;
317 length -= this_xfer;
318
319 /* setup the retry counter */
320 maxtry = 10;
321
322 /* set up the transfer loop */
323 do {
324 /* transfer the data */
Simon Glass332a9b62015-03-25 12:22:14 -0600325 debug("Bulk xfer 0x%lx(%d) try #%d\n",
326 (ulong)map_to_sysmem(buf), this_xfer,
327 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000328 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100329 this_xfer, &partial,
330 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530331 debug("bulk_msg returned %d xferred %d/%d\n",
332 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100333 if (us->pusb_dev->status != 0) {
334 /* if we stall, we need to clear it before
335 * we go on
336 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530337#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000338 display_int_status(us->pusb_dev->status);
339#endif
340 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530341 debug("stalled ->clearing endpoint" \
342 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000343 stat = us->pusb_dev->status;
344 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100345 us->pusb_dev->status = stat;
346 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530347 debug("bulk transferred" \
348 "with error %lX," \
349 " but data ok\n",
350 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000351 return 0;
352 }
353 else
354 return result;
355 }
356 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530357 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000358 return result;
359 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530360 debug("bulk transferred with error");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100361 if (this_xfer == partial) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530362 debug(" %ld, but data ok\n",
363 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000364 return 0;
365 }
366 /* if our try counter reaches 0, bail out */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530367 debug(" %ld, data %d\n",
368 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000369 if (!maxtry--)
370 return result;
371 }
372 /* update to show what data was transferred */
373 this_xfer -= partial;
374 buf += partial;
375 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100376 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000377 }
378
379 /* if we get here, we're done and successful */
380 return 0;
381}
382
wdenkde887eb2003-09-10 18:20:28 +0000383static int usb_stor_BBB_reset(struct us_data *us)
384{
385 int result;
386 unsigned int pipe;
387
388 /*
389 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
390 *
391 * For Reset Recovery the host shall issue in the following order:
392 * a) a Bulk-Only Mass Storage Reset
393 * b) a Clear Feature HALT to the Bulk-In endpoint
394 * c) a Clear Feature HALT to the Bulk-Out endpoint
395 *
396 * This is done in 3 steps.
397 *
398 * If the reset doesn't succeed, the device should be port reset.
399 *
400 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
401 */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530402 debug("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100403 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
404 US_BBB_RESET,
405 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillipsb052b602012-10-29 13:34:32 +0000406 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200407
Michael Trimarchi956a4352008-12-10 15:52:06 +0100408 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530409 debug("RESET:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000410 return -1;
411 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200412
wdenkde887eb2003-09-10 18:20:28 +0000413 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000414 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530415 debug("BBB_reset result %d: status %lX reset\n",
416 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000417 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
418 result = usb_clear_halt(us->pusb_dev, pipe);
419 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000420 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530421 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
422 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000423 /* long wait for reset */
424 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
425 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000426 mdelay(150);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530427 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
428 result, us->pusb_dev->status);
429 debug("BBB_reset done\n");
wdenkde887eb2003-09-10 18:20:28 +0000430 return 0;
431}
432
wdenkaffae2b2002-08-17 09:36:01 +0000433/* FIXME: this reset function doesn't really reset the port, and it
434 * should. Actually it should probably do what it's doing here, and
435 * reset the port physically
436 */
437static int usb_stor_CB_reset(struct us_data *us)
438{
439 unsigned char cmd[12];
440 int result;
441
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530442 debug("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100443 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000444 cmd[0] = SCSI_SEND_DIAG;
445 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100446 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
447 US_CBI_ADSC,
448 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
449 0, us->ifnum, cmd, sizeof(cmd),
450 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000451
452 /* long wait for reset */
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000453 mdelay(1500);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530454 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
455 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000456 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
457 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
458
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530459 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000460 return 0;
461}
462
wdenkde887eb2003-09-10 18:20:28 +0000463/*
464 * Set up the command for a BBB device. Note that the actual SCSI
465 * command is copied into cbw.CBWCDB.
466 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000467static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000468{
469 int result;
470 int actlen;
471 int dir_in;
472 unsigned int pipe;
Simon Glass6f414652015-03-25 12:22:11 -0600473 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000474
475 dir_in = US_DIRECTION(srb->cmd[0]);
476
477#ifdef BBB_COMDAT_TRACE
Vivek Gautam23cbd292013-04-12 16:34:34 +0530478 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100479 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
480 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000481 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100482 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000483 printf("cmd[%d] %#x ", result, srb->cmd[result]);
484 printf("\n");
485 }
486#endif
487 /* sanity checks */
488 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530489 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenkde887eb2003-09-10 18:20:28 +0000490 return -1;
491 }
492
493 /* always OUT to the ep */
494 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
495
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530496 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
497 cbw->dCBWTag = cpu_to_le32(CBWTag++);
498 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
499 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
500 cbw->bCBWLUN = srb->lun;
501 cbw->bCDBLength = srb->cmdlen;
wdenkde887eb2003-09-10 18:20:28 +0000502 /* copy the command data into the CBW command data buffer */
503 /* DST SRC LEN!!! */
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300504
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530505 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
506 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100507 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000508 if (result < 0)
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530509 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenkde887eb2003-09-10 18:20:28 +0000510 return result;
511}
512
wdenkaffae2b2002-08-17 09:36:01 +0000513/* FIXME: we also need a CBI_command which sets up the completion
514 * interrupt, and waits for it
515 */
Kim Phillipsb052b602012-10-29 13:34:32 +0000516static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000517{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200518 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100519 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000520 unsigned int pipe;
521 unsigned long status;
522
Michael Trimarchi956a4352008-12-10 15:52:06 +0100523 retry = 5;
524 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000525
Michael Trimarchi956a4352008-12-10 15:52:06 +0100526 if (dir_in)
527 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
528 else
529 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
530
531 while (retry--) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530532 debug("CBI gets a command: Try %d\n", 5 - retry);
533#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000534 usb_show_srb(srb);
535#endif
536 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100537 result = usb_control_msg(us->pusb_dev,
538 usb_sndctrlpipe(us->pusb_dev , 0),
539 US_CBI_ADSC,
540 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000541 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100542 srb->cmd, srb->cmdlen,
543 USB_CNTL_TIMEOUT * 5);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530544 debug("CB_transport: control msg returned %d, status %lX\n",
545 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000546 /* check the return code for the command */
547 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100548 if (us->pusb_dev->status & USB_ST_STALLED) {
549 status = us->pusb_dev->status;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530550 debug(" stall during command found," \
551 " clear pipe\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100552 usb_clear_halt(us->pusb_dev,
553 usb_sndctrlpipe(us->pusb_dev, 0));
554 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000555 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530556 debug(" error during command %02X" \
557 " Stat = %lX\n", srb->cmd[0],
558 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000559 return result;
560 }
561 /* transfer the data payload for this command, if one exists*/
562
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530563 debug("CB_transport: control msg returned %d," \
564 " direction is %s to go 0x%lx\n", result,
565 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000566 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100567 result = us_one_transfer(us, pipe, (char *)srb->pdata,
568 srb->datalen);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530569 debug("CBI attempted to transfer data," \
570 " result is %d status %lX, len %d\n",
571 result, us->pusb_dev->status,
572 us->pusb_dev->act_len);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100573 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000574 break;
575 } /* if (srb->datalen) */
576 else
577 break;
578 }
579 /* return result */
580
581 return result;
582}
583
584
Kim Phillipsb052b602012-10-29 13:34:32 +0000585static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000586{
587 int timeout;
588
wdenk5f495752004-02-26 23:46:20 +0000589 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000591 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
592 timeout = 1000;
593 while (timeout--) {
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300594 if (us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000595 break;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000596 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000597 }
598 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100599 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000600 us->ip_wanted = 0;
601 return USB_STOR_TRANSPORT_ERROR;
602 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530603 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
604 us->ip_data, us->pusb_dev->irq_act_len,
605 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000606 /* UFI gives us ASC and ASCQ, like a request sense */
607 if (us->subclass == US_SC_UFI) {
608 if (srb->cmd[0] == SCSI_REQ_SENSE ||
609 srb->cmd[0] == SCSI_INQUIRY)
610 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000611 else if (us->ip_data)
612 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000613 else
wdenk5f495752004-02-26 23:46:20 +0000614 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000615 }
616 /* otherwise, we interpret the data normally */
617 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000618 case 0x0001:
619 return USB_STOR_TRANSPORT_GOOD;
620 case 0x0002:
621 return USB_STOR_TRANSPORT_FAILED;
622 default:
623 return USB_STOR_TRANSPORT_ERROR;
624 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000625 return USB_STOR_TRANSPORT_ERROR;
626}
627
628#define USB_TRANSPORT_UNKNOWN_RETRY 5
629#define USB_TRANSPORT_NOT_READY_RETRY 10
630
wdenkde887eb2003-09-10 18:20:28 +0000631/* clear a stall on an endpoint - special for BBB devices */
Kim Phillipsb052b602012-10-29 13:34:32 +0000632static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenkde887eb2003-09-10 18:20:28 +0000633{
634 int result;
635
636 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100637 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000638 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillipsb052b602012-10-29 13:34:32 +0000639 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000640 return result;
641}
642
Kim Phillipsb052b602012-10-29 13:34:32 +0000643static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenkde887eb2003-09-10 18:20:28 +0000644{
645 int result, retry;
646 int dir_in;
647 int actlen, data_actlen;
648 unsigned int pipe, pipein, pipeout;
Simon Glass6f414652015-03-25 12:22:11 -0600649 ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
wdenkde887eb2003-09-10 18:20:28 +0000650#ifdef BBB_XPORT_TRACE
651 unsigned char *ptr;
652 int index;
653#endif
654
655 dir_in = US_DIRECTION(srb->cmd[0]);
656
657 /* COMMAND phase */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530658 debug("COMMAND phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000659 result = usb_stor_BBB_comdat(srb, us);
660 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530661 debug("failed to send CBW status %ld\n",
662 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000663 usb_stor_BBB_reset(us);
664 return USB_STOR_TRANSPORT_FAILED;
665 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200666 if (!(us->flags & USB_READY))
667 mdelay(5);
wdenkde887eb2003-09-10 18:20:28 +0000668 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
669 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
670 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000671 data_actlen = 0;
672 /* no data, go immediately to the STATUS phase */
673 if (srb->datalen == 0)
674 goto st;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530675 debug("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000676 if (dir_in)
677 pipe = pipein;
678 else
679 pipe = pipeout;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +0300680
Michael Trimarchi956a4352008-12-10 15:52:06 +0100681 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
682 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000683 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100684 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530685 debug("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000686 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100687 result = usb_stor_BBB_clear_endpt_stall(us,
688 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000689 if (result >= 0)
690 /* continue on to STATUS phase */
691 goto st;
692 }
693 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530694 debug("usb_bulk_msg error status %ld\n",
695 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000696 usb_stor_BBB_reset(us);
697 return USB_STOR_TRANSPORT_FAILED;
698 }
699#ifdef BBB_XPORT_TRACE
700 for (index = 0; index < data_actlen; index++)
701 printf("pdata[%d] %#x ", index, srb->pdata[index]);
702 printf("\n");
703#endif
704 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100705st:
wdenkde887eb2003-09-10 18:20:28 +0000706 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100707again:
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530708 debug("STATUS phase\n");
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530709 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200710 &actlen, USB_CNTL_TIMEOUT*5);
711
wdenkde887eb2003-09-10 18:20:28 +0000712 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100713 if ((result < 0) && (retry < 1) &&
714 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530715 debug("STATUS:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000716 /* clear the STALL on the endpoint */
717 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
718 if (result >= 0 && (retry++ < 1))
719 /* do a retry */
720 goto again;
721 }
722 if (result < 0) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530723 debug("usb_bulk_msg error status %ld\n",
724 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000725 usb_stor_BBB_reset(us);
726 return USB_STOR_TRANSPORT_FAILED;
727 }
728#ifdef BBB_XPORT_TRACE
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530729 ptr = (unsigned char *)csw;
wdenkde887eb2003-09-10 18:20:28 +0000730 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
731 printf("ptr[%d] %#x ", index, ptr[index]);
732 printf("\n");
733#endif
734 /* misuse pipe to get the residue */
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530735 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000736 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
737 pipe = srb->datalen - data_actlen;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530738 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530739 debug("!CSWSIGNATURE\n");
wdenkde887eb2003-09-10 18:20:28 +0000740 usb_stor_BBB_reset(us);
741 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530742 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530743 debug("!Tag\n");
wdenkde887eb2003-09-10 18:20:28 +0000744 usb_stor_BBB_reset(us);
745 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530746 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530747 debug(">PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000748 usb_stor_BBB_reset(us);
749 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530750 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530751 debug("=PHASE\n");
wdenkde887eb2003-09-10 18:20:28 +0000752 usb_stor_BBB_reset(us);
753 return USB_STOR_TRANSPORT_FAILED;
754 } else if (data_actlen > srb->datalen) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530755 debug("transferred %dB instead of %ldB\n",
756 data_actlen, srb->datalen);
wdenkde887eb2003-09-10 18:20:28 +0000757 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxena6c9bb602012-04-03 14:56:06 +0530758 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530759 debug("FAILED\n");
wdenkde887eb2003-09-10 18:20:28 +0000760 return USB_STOR_TRANSPORT_FAILED;
761 }
762
763 return result;
764}
765
Kim Phillipsb052b602012-10-29 13:34:32 +0000766static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000767{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100768 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000769 ccb *psrb;
770 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100771 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000772
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200773 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100774 status = USB_STOR_TRANSPORT_GOOD;
775 retry = 0;
776 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000777 /* issue the command */
778do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100779 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530780 debug("command / Data returned %d, status %lX\n",
781 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000782 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100783 if (us->protocol == US_PR_CBI) {
784 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000785 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100786 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530787 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000788 return status;
789 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100790 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
791 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
792 if (!us->ip_data) {
793 /* if the status is good, report it */
794 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530795 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000796 return status;
797 }
798 }
799 }
800 /* do we have to issue an auto request? */
801 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100802 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530803 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000804 us->transport_reset(us);
805 return USB_STOR_TRANSPORT_ERROR;
806 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100807 if ((us->protocol == US_PR_CBI) &&
808 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
809 (srb->cmd[0] == SCSI_INQUIRY))) {
810 /* do not issue an autorequest after request sense */
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530811 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000812 return USB_STOR_TRANSPORT_GOOD;
813 }
814 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100815 memset(&psrb->cmd[0], 0, 12);
816 psrb->cmd[0] = SCSI_REQ_SENSE;
817 psrb->cmd[1] = srb->lun << 5;
818 psrb->cmd[4] = 18;
819 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200820 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100821 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000822 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100823 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530824 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000825 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100826 if (us->protocol == US_PR_CBI)
827 status = usb_stor_CBI_get_status(psrb, us);
828
829 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530830 debug(" AUTO REQUEST ERROR %ld\n",
831 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000832 return USB_STOR_TRANSPORT_ERROR;
833 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530834 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
835 srb->sense_buf[0], srb->sense_buf[2],
836 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000837 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100838 if ((srb->sense_buf[2] == 0) &&
839 (srb->sense_buf[12] == 0) &&
840 (srb->sense_buf[13] == 0)) {
841 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000842 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100843 }
844
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100846 switch (srb->sense_buf[2]) {
847 case 0x01:
848 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000849 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000850 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100851 case 0x02:
852 /* Not Ready */
853 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
854 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
855 " 0x%02X (NOT READY)\n", srb->cmd[0],
856 srb->sense_buf[0], srb->sense_buf[2],
857 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000858 return USB_STOR_TRANSPORT_FAILED;
859 } else {
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000860 mdelay(100);
wdenkde887eb2003-09-10 18:20:28 +0000861 goto do_retry;
862 }
863 break;
864 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100865 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
866 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
867 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
868 srb->sense_buf[2], srb->sense_buf[12],
869 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000870 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100871 } else
wdenkde887eb2003-09-10 18:20:28 +0000872 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000873 break;
wdenkaffae2b2002-08-17 09:36:01 +0000874 }
875 return USB_STOR_TRANSPORT_FAILED;
876}
877
878
Michael Trimarchi956a4352008-12-10 15:52:06 +0100879static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000880{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100881 int retry, i;
882 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000883 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100884 memset(&srb->cmd[0], 0, 12);
885 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200886 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100887 srb->cmd[4] = 36;
888 srb->datalen = 36;
889 srb->cmdlen = 12;
890 i = ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530891 debug("inquiry returns %d\n", i);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100892 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000893 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200894 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000895
Michael Trimarchi956a4352008-12-10 15:52:06 +0100896 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000897 printf("error in inquiry\n");
898 return -1;
899 }
900 return 0;
901}
902
Michael Trimarchi956a4352008-12-10 15:52:06 +0100903static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000904{
905 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000906
Michael Trimarchi956a4352008-12-10 15:52:06 +0100907 ptr = (char *)srb->pdata;
908 memset(&srb->cmd[0], 0, 12);
909 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200910 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100911 srb->cmd[4] = 18;
912 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200913 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100914 srb->cmdlen = 12;
915 ss->transport(srb, ss);
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530916 debug("Request Sense returned %02X %02X %02X\n",
917 srb->sense_buf[2], srb->sense_buf[12],
918 srb->sense_buf[13]);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100919 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000920 return 0;
921}
922
Michael Trimarchi956a4352008-12-10 15:52:06 +0100923static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000924{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200925 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000926
wdenkaffae2b2002-08-17 09:36:01 +0000927 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100928 memset(&srb->cmd[0], 0, 12);
929 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200930 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100931 srb->datalen = 0;
932 srb->cmdlen = 12;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200933 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
934 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000935 return 0;
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +0200936 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100937 usb_request_sense(srb, ss);
Vincent Palatin976b3232012-12-12 17:55:29 -0800938 /*
939 * Check the Key Code Qualifier, if it matches
940 * "Not Ready - medium not present"
941 * (the sense Key equals 0x2 and the ASC is 0x3a)
942 * return immediately as the medium being absent won't change
943 * unless there is a user action.
944 */
945 if ((srb->sense_buf[2] == 0x02) &&
946 (srb->sense_buf[12] == 0x3a))
947 return -1;
Mike Frysinger60ce19a2012-03-05 13:47:00 +0000948 mdelay(100);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100949 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000950
wdenkaffae2b2002-08-17 09:36:01 +0000951 return -1;
952}
953
Michael Trimarchi956a4352008-12-10 15:52:06 +0100954static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000955{
956 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100957 /* XXX retries */
958 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000959 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100960 memset(&srb->cmd[0], 0, 12);
961 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200962 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100963 srb->datalen = 8;
964 srb->cmdlen = 12;
965 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000966 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100967 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000968
wdenkaffae2b2002-08-17 09:36:01 +0000969 return -1;
970}
971
Michael Trimarchi956a4352008-12-10 15:52:06 +0100972static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
973 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000974{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100975 memset(&srb->cmd[0], 0, 12);
976 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200977 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100978 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
979 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
980 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
981 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
982 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
983 srb->cmd[8] = (unsigned char) blocks & 0xff;
984 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +0530985 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100986 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000987}
988
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530989static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
990 unsigned short blocks)
991{
992 memset(&srb->cmd[0], 0, 12);
993 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200994 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530995 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
996 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
997 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
998 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
999 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1000 srb->cmd[8] = (unsigned char) blocks & 0xff;
1001 srb->cmdlen = 12;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301002 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301003 return ss->transport(srb, ss);
1004}
1005
wdenkaffae2b2002-08-17 09:36:01 +00001006
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001007#ifdef CONFIG_USB_BIN_FIXUP
1008/*
1009 * Some USB storage devices queried for SCSI identification data respond with
1010 * binary strings, which if output to the console freeze the terminal. The
1011 * workaround is to modify the vendor and product strings read from such
1012 * device with proper values (as reported by 'usb info').
1013 *
1014 * Vendor and product length limits are taken from the definition of
1015 * block_dev_desc_t in include/part.h.
1016 */
1017static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1018 unsigned char vendor[],
1019 unsigned char product[]) {
1020 const unsigned char max_vendor_len = 40;
1021 const unsigned char max_product_len = 20;
1022 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001023 strncpy((char *)vendor, "SMSC", max_vendor_len);
1024 strncpy((char *)product, "Flash Media Cntrller",
1025 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001026 }
1027}
1028#endif /* CONFIG_USB_BIN_FIXUP */
1029
Stephen Warrene73f2962015-12-07 11:38:48 -07001030static unsigned long usb_stor_read(block_dev_desc_t *block_dev, lbaint_t blknr,
1031 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001032{
Stephen Warrene73f2962015-12-07 11:38:48 -07001033 int device = block_dev->dev;
Gabe Black7d077682012-10-12 14:26:07 +00001034 lbaint_t start, blks;
1035 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001036 unsigned short smallblks;
1037 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001038 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001039 int retry;
wdenk0e2874cb2004-03-02 14:05:39 +00001040 ccb *srb = &usb_ccb;
1041
1042 if (blkcnt == 0)
1043 return 0;
1044
1045 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001046 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001047 debug("\nusb_read: dev %d\n", device);
1048 dev = usb_dev_desc[device].priv;
1049 if (!dev) {
1050 debug("%s: No device\n", __func__);
1051 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001052 }
Kyle Moffett6540db02011-12-21 07:08:12 +00001053 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001054
1055 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001056 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001057 buf_addr = (uintptr_t)buffer;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001058 start = blknr;
1059 blks = blkcnt;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001060
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301061 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001062 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001063
wdenkaffae2b2002-08-17 09:36:01 +00001064 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001065 /* XXX need some comment here */
1066 retry = 2;
1067 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001068 if (blks > USB_MAX_XFER_BLK)
1069 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001070 else
1071 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001072retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001073 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001074 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001075 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1076 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001077 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301078 debug("Read ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001079 usb_request_sense(srb, ss);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001080 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001081 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001082 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001083 break;
1084 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001085 start += smallblks;
1086 blks -= smallblks;
1087 buf_addr += srb->datalen;
1088 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001089 ss->flags &= ~USB_READY;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001090
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301091 debug("usb_read: end startblk " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001092 ", blccnt %x buffer %" PRIxPTR "\n",
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301093 start, smallblks, buf_addr);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001094
wdenkaffae2b2002-08-17 09:36:01 +00001095 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001096 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001097 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001098 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001099}
1100
Stephen Warrene73f2962015-12-07 11:38:48 -07001101static unsigned long usb_stor_write(block_dev_desc_t *block_dev, lbaint_t blknr,
1102 lbaint_t blkcnt, const void *buffer)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301103{
Stephen Warrene73f2962015-12-07 11:38:48 -07001104 int device = block_dev->dev;
Gabe Black7d077682012-10-12 14:26:07 +00001105 lbaint_t start, blks;
1106 uintptr_t buf_addr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301107 unsigned short smallblks;
1108 struct usb_device *dev;
Kyle Moffett6540db02011-12-21 07:08:12 +00001109 struct us_data *ss;
Simon Glass5c3c91c2015-03-25 12:22:13 -06001110 int retry;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301111 ccb *srb = &usb_ccb;
1112
1113 if (blkcnt == 0)
1114 return 0;
1115
1116 device &= 0xff;
1117 /* Setup device */
Simon Glass5c3c91c2015-03-25 12:22:13 -06001118 debug("\nusb_write: dev %d\n", device);
1119 dev = usb_dev_desc[device].priv;
1120 if (!dev)
1121 return 0;
Kyle Moffett6540db02011-12-21 07:08:12 +00001122 ss = (struct us_data *)dev->privptr;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301123
1124 usb_disable_asynch(1); /* asynch transfer not allowed */
1125
1126 srb->lun = usb_dev_desc[device].lun;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001127 buf_addr = (uintptr_t)buffer;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301128 start = blknr;
1129 blks = blkcnt;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301130
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301131 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
Simon Glassb43f7682014-10-15 04:38:38 -06001132 " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301133
1134 do {
1135 /* If write fails retry for max retry count else
1136 * return with number of blocks written successfully.
1137 */
1138 retry = 2;
1139 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001140 if (blks > USB_MAX_XFER_BLK)
1141 smallblks = USB_MAX_XFER_BLK;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301142 else
1143 smallblks = (unsigned short) blks;
1144retry_it:
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001145 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301146 usb_show_progress();
1147 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1148 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett6540db02011-12-21 07:08:12 +00001149 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301150 debug("Write ERROR\n");
Kyle Moffett6540db02011-12-21 07:08:12 +00001151 usb_request_sense(srb, ss);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301152 if (retry--)
1153 goto retry_it;
1154 blkcnt -= blks;
1155 break;
1156 }
1157 start += smallblks;
1158 blks -= smallblks;
1159 buf_addr += srb->datalen;
1160 } while (blks != 0);
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001161 ss->flags &= ~USB_READY;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301162
Simon Glassb43f7682014-10-15 04:38:38 -06001163 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
1164 PRIxPTR "\n", start, smallblks, buf_addr);
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301165
1166 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeaudfa2bcc2012-08-10 18:23:25 +02001167 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001168 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301169 return blkcnt;
1170
1171}
wdenkaffae2b2002-08-17 09:36:01 +00001172
1173/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001174int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1175 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001176{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001177 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001178 int i;
Vivek Gautam23cbd292013-04-12 16:34:34 +05301179 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001180 unsigned int flags = 0;
1181
wdenkaffae2b2002-08-17 09:36:01 +00001182 /* let's examine the device now */
1183 iface = &dev->config.if_desc[ifnum];
1184
wdenkaffae2b2002-08-17 09:36:01 +00001185 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001186 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1187 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1188 iface->desc.bInterfaceSubClass > US_SC_MAX) {
Simon Glass78330d62015-03-25 12:22:12 -06001189 debug("Not mass storage\n");
wdenkaffae2b2002-08-17 09:36:01 +00001190 /* if it's not a mass storage, we go no further */
1191 return 0;
1192 }
1193
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001194 memset(ss, 0, sizeof(struct us_data));
1195
wdenkaffae2b2002-08-17 09:36:01 +00001196 /* At this point, we know we've got a live one */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301197 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001198
1199 /* Initialize the us_data structure with some useful info */
1200 ss->flags = flags;
1201 ss->ifnum = ifnum;
1202 ss->pusb_dev = dev;
1203 ss->attention_done = 0;
Tom Rinid83b89d2015-10-11 07:26:27 -04001204 ss->subclass = iface->desc.bInterfaceSubClass;
1205 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001206
1207 /* set the handler pointers based on the protocol */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301208 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001209 switch (ss->protocol) {
1210 case US_PR_CB:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301211 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001212 ss->transport = usb_stor_CB_transport;
1213 ss->transport_reset = usb_stor_CB_reset;
1214 break;
1215
1216 case US_PR_CBI:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301217 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001218 ss->transport = usb_stor_CB_transport;
1219 ss->transport_reset = usb_stor_CB_reset;
1220 break;
wdenkde887eb2003-09-10 18:20:28 +00001221 case US_PR_BULK:
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301222 debug("Bulk/Bulk/Bulk\n");
wdenkde887eb2003-09-10 18:20:28 +00001223 ss->transport = usb_stor_BBB_transport;
1224 ss->transport_reset = usb_stor_BBB_reset;
1225 break;
wdenkaffae2b2002-08-17 09:36:01 +00001226 default:
wdenk5f495752004-02-26 23:46:20 +00001227 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001228 return 0;
1229 break;
1230 }
1231
1232 /*
1233 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1234 * An optional interrupt is OK (necessary for CBI protocol).
1235 * We will ignore any others.
1236 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001237 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301238 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001239 /* is it an BULK endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301240 if ((ep_desc->bmAttributes &
Michael Trimarchi956a4352008-12-10 15:52:06 +01001241 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam23cbd292013-04-12 16:34:34 +05301242 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1243 ss->ep_in = ep_desc->bEndpointAddress &
1244 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001245 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001246 ss->ep_out =
Vivek Gautam23cbd292013-04-12 16:34:34 +05301247 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001248 USB_ENDPOINT_NUMBER_MASK;
1249 }
1250
1251 /* is it an interrupt endpoint? */
Vivek Gautam23cbd292013-04-12 16:34:34 +05301252 if ((ep_desc->bmAttributes &
1253 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1254 ss->ep_int = ep_desc->bEndpointAddress &
1255 USB_ENDPOINT_NUMBER_MASK;
1256 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001257 }
1258 }
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301259 debug("Endpoints In %d Out %d Int %d\n",
1260 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001261
1262 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001263 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001264 !ss->ep_in || !ss->ep_out ||
1265 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301266 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001267 return 0;
1268 }
1269 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001270 /* We only handle certain protocols. Currently, these are
1271 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001272 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001273 */
wdenk5f495752004-02-26 23:46:20 +00001274 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1275 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001276 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001277 return 0;
1278 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001279 if (ss->ep_int) {
1280 /* we had found an interrupt endpoint, prepare irq pipe
1281 * set up the IRQ pipe and handler
1282 */
wdenkaffae2b2002-08-17 09:36:01 +00001283 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1284 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1285 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001286 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001287 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001288 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001289 return 1;
1290}
1291
Michael Trimarchi956a4352008-12-10 15:52:06 +01001292int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1293 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001294{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001295 unsigned char perq, modi;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001296 ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
1297 ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
1298 u32 capacity, blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001299 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001300
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001301 pccb->pdata = usb_stor_buf;
1302
1303 dev_desc->target = dev->devnum;
1304 pccb->lun = dev_desc->lun;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301305 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001306
Simon Glass78330d62015-03-25 12:22:12 -06001307 if (usb_inquiry(pccb, ss)) {
1308 debug("%s: usb_inquiry() failed\n", __func__);
wdenkaffae2b2002-08-17 09:36:01 +00001309 return -1;
Simon Glass78330d62015-03-25 12:22:12 -06001310 }
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001311
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001312 perq = usb_stor_buf[0];
1313 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001314
Soeren Moche4828002014-11-08 07:02:14 +01001315 /*
1316 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
1317 * they would not respond to test_unit_ready .
1318 */
1319 if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
Simon Glass78330d62015-03-25 12:22:12 -06001320 debug("%s: unknown/unsupported device\n", __func__);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001321 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001322 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001323 if ((modi&0x80) == 0x80) {
1324 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001325 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001326 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001327 memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
1328 memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
1329 memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001330 dev_desc->vendor[8] = 0;
1331 dev_desc->product[16] = 0;
1332 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001333#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001334 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1335 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001336#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301337 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1338 usb_stor_buf[3]);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001339 if (usb_test_unit_ready(pccb, ss)) {
1340 printf("Device NOT ready\n"
1341 " Request Sense returned %02X %02X %02X\n",
1342 pccb->sense_buf[2], pccb->sense_buf[12],
1343 pccb->sense_buf[13]);
1344 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001345 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001346 return 1;
1347 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001348 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001349 }
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001350 pccb->pdata = (unsigned char *)cap;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001351 memset(pccb->pdata, 0, 8);
1352 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001353 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001354 cap[0] = 2880;
1355 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001356 }
Benoît Thébaudeaufbf909a2012-08-10 18:27:11 +02001357 ss->flags &= ~USB_READY;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001358 debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001359#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001360 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1361 cap[0] >>= 16;
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001362
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001363 cap[0] = cpu_to_be32(cap[0]);
1364 cap[1] = cpu_to_be32(cap[1]);
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001365#endif
1366
1367 capacity = be32_to_cpu(cap[0]) + 1;
1368 blksz = be32_to_cpu(cap[1]);
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001369
Sergey Temerkhanov57236d52015-04-01 17:18:46 +03001370 debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
1371 dev_desc->lba = capacity;
1372 dev_desc->blksz = blksz;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001373 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001374 dev_desc->type = perq;
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301375 debug(" address %d\n", dev_desc->target);
1376 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001377
1378 init_part(dev_desc);
1379
Vivek Gautamf94c95d2013-04-12 16:34:33 +05301380 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001381 return 1;
1382}
Simon Glassac9774e2015-03-25 12:22:16 -06001383
1384#ifdef CONFIG_DM_USB
1385
1386static int usb_mass_storage_probe(struct udevice *dev)
1387{
Simon Glassde44acf2015-09-28 23:32:01 -06001388 struct usb_device *udev = dev_get_parent_priv(dev);
Simon Glassac9774e2015-03-25 12:22:16 -06001389 int ret;
1390
1391 usb_disable_asynch(1); /* asynch transfer not allowed */
1392 ret = usb_stor_probe_device(udev);
1393 usb_disable_asynch(0); /* asynch transfer allowed */
1394
1395 return ret;
1396}
1397
1398static const struct udevice_id usb_mass_storage_ids[] = {
1399 { .compatible = "usb-mass-storage" },
1400 { }
1401};
1402
1403U_BOOT_DRIVER(usb_mass_storage) = {
1404 .name = "usb_mass_storage",
1405 .id = UCLASS_MASS_STORAGE,
1406 .of_match = usb_mass_storage_ids,
1407 .probe = usb_mass_storage_probe,
1408};
1409
1410UCLASS_DRIVER(usb_mass_storage) = {
1411 .id = UCLASS_MASS_STORAGE,
1412 .name = "usb_mass_storage",
1413};
1414
1415static const struct usb_device_id mass_storage_id_table[] = {
1416 {
1417 .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
1418 .bInterfaceClass = USB_CLASS_MASS_STORAGE
1419 },
1420 { } /* Terminating entry */
1421};
1422
Simon Glass46952fb2015-07-06 16:47:51 -06001423U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
Simon Glassac9774e2015-03-25 12:22:16 -06001424
1425#endif