blob: faad23706f8d8bca3d3bd08f9ef1d5a4efcd5d38 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-08-04 01:14:12 +02002 * Most of this source has been derived from the Linux USB
3 * project:
4 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
5 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
6 * (c) 1999 Michael Gee (michael@linuxspecific.com)
7 * (c) 2000 Yggdrasil Computing, Inc.
8 *
9 *
10 * Adapted for U-Boot:
11 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
wdenkaffae2b2002-08-17 09:36:01 +000012 *
wdenk149dded2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000015 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000017 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000018 *
19 * See file CREDITS for list of people who contributed to this
20 * project.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; either version 2 of
25 * the License, or (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wdenk80885a92004-02-26 23:46:20 +000029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenkaffae2b2002-08-17 09:36:01 +000030 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35 * MA 02111-1307 USA
36 *
37 */
38
39/* Note:
40 * Currently only the CBI transport protocoll has been implemented, and it
41 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
42 * transport protocoll may work as well.
43 */
wdenk149dded2003-09-10 18:20:28 +000044/*
45 * New Note:
46 * Support for USB Mass Storage Devices (BBB) has been added. It has
47 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000048 */
wdenkaffae2b2002-08-17 09:36:01 +000049
50
wdenkaffae2b2002-08-17 09:36:01 +000051#include <common.h>
52#include <command.h>
Christian Eggersc9182612008-05-21 22:12:00 +020053#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000054#include <asm/processor.h>
55
Grant Likely735dd972007-02-20 09:04:34 +010056#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000057#include <usb.h>
58
wdenk80885a92004-02-26 23:46:20 +000059#undef BBB_COMDAT_TRACE
60#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000061
62#ifdef USB_STOR_DEBUG
Marek Vasut86bd3ff2011-10-25 11:39:16 +020063#define USB_BLK_DEBUG 1
wdenkaffae2b2002-08-17 09:36:01 +000064#else
Marek Vasut86bd3ff2011-10-25 11:39:16 +020065#define USB_BLK_DEBUG 0
wdenkaffae2b2002-08-17 09:36:01 +000066#endif
67
Marek Vasut86bd3ff2011-10-25 11:39:16 +020068#define USB_STOR_PRINTF(fmt, args...) debug_cond(USB_BLK_DEBUG, fmt, ##args)
69
wdenkaffae2b2002-08-17 09:36:01 +000070#include <scsi.h>
71/* direction table -- this indicates the direction of the data
72 * transfer for each command code -- a 1 indicates input
73 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040074static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000075 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
76 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
79};
80#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
81
Puneet Saxenaf5766132012-04-03 14:56:06 +053082static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
wdenkaffae2b2002-08-17 09:36:01 +000083
84/*
85 * CBI style
86 */
87
88#define US_CBI_ADSC 0
89
wdenk149dded2003-09-10 18:20:28 +000090/*
91 * BULK only
92 */
93#define US_BBB_RESET 0xff
94#define US_BBB_GET_MAX_LUN 0xfe
95
96/* Command Block Wrapper */
97typedef struct {
98 __u32 dCBWSignature;
99# define CBWSIGNATURE 0x43425355
100 __u32 dCBWTag;
101 __u32 dCBWDataTransferLength;
102 __u8 bCBWFlags;
103# define CBWFLAGS_OUT 0x00
104# define CBWFLAGS_IN 0x80
105 __u8 bCBWLUN;
106 __u8 bCDBLength;
107# define CBWCDBLENGTH 16
108 __u8 CBWCDB[CBWCDBLENGTH];
109} umass_bbb_cbw_t;
wdenk80885a92004-02-26 23:46:20 +0000110#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100111static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +0000112
113/* Command Status Wrapper */
114typedef struct {
115 __u32 dCSWSignature;
116# define CSWSIGNATURE 0x53425355
117 __u32 dCSWTag;
118 __u32 dCSWDataResidue;
119 __u8 bCSWStatus;
120# define CSWSTATUS_GOOD 0x0
wdenk80885a92004-02-26 23:46:20 +0000121# define CSWSTATUS_FAILED 0x1
wdenk149dded2003-09-10 18:20:28 +0000122# define CSWSTATUS_PHASE 0x2
123} umass_bbb_csw_t;
wdenk80885a92004-02-26 23:46:20 +0000124#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000125
126#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100127static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000128
129static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
130
131struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100132typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
133typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000134
135struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100136 struct usb_device *pusb_dev; /* this usb_device */
137
138 unsigned int flags; /* from filter initially */
139 unsigned char ifnum; /* interface number */
140 unsigned char ep_in; /* in endpoint */
141 unsigned char ep_out; /* out ....... */
142 unsigned char ep_int; /* interrupt . */
143 unsigned char subclass; /* as in overview */
144 unsigned char protocol; /* .............. */
145 unsigned char attention_done; /* force attn on first cmd */
146 unsigned short ip_data; /* interrupt data */
147 int action; /* what to do */
148 int ip_wanted; /* needed */
149 int *irq_handle; /* for USB int requests */
150 unsigned int irqpipe; /* pipe for release_irq */
151 unsigned char irqmaxp; /* max packed for irq Pipe */
152 unsigned char irqinterval; /* Intervall for IRQ Pipe */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +0000153 unsigned long max_xfer_blk; /* Max blocks per xfer */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100154 ccb *srb; /* current srb */
155 trans_reset transport_reset; /* reset routine */
156 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000157};
158
159static struct us_data usb_stor[USB_MAX_STOR_DEV];
160
161
wdenk80885a92004-02-26 23:46:20 +0000162#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000163#define USB_STOR_TRANSPORT_FAILED -1
164#define USB_STOR_TRANSPORT_ERROR -2
165
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100166int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
167 block_dev_desc_t *dev_desc);
168int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
169 struct us_data *ss);
170unsigned long usb_stor_read(int device, unsigned long blknr,
171 unsigned long blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530172unsigned long usb_stor_write(int device, unsigned long blknr,
173 unsigned long blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000174struct usb_device * usb_get_dev_index(int index);
175void uhci_show_temp_int_td(void);
176
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000177#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000178block_dev_desc_t *usb_stor_get_dev(int index)
179{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200180 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000181}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000182#endif
wdenkaffae2b2002-08-17 09:36:01 +0000183
184void usb_show_progress(void)
185{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200186 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000187}
188
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100189/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200190 * show info on storage devices; 'usb start/init' must be invoked earlier
191 * as we only retrieve structures populated during devices initialization
192 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100193int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200194{
195 int i;
196
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100197 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200198 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100199 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200200 dev_print(&usb_dev_desc[i]);
201 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100202 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100203 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700204
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100205 printf("No storage devices, perhaps not 'usb start'ed..?\n");
206 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200207}
208
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200209static unsigned int usb_get_max_lun(struct us_data *us)
210{
211 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530212 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200213 len = usb_control_msg(us->pusb_dev,
214 usb_rcvctrlpipe(us->pusb_dev, 0),
215 US_BBB_GET_MAX_LUN,
216 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
217 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530218 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200219 USB_CNTL_TIMEOUT * 5);
220 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
Puneet Saxenaf5766132012-04-03 14:56:06 +0530221 len, (int) *result);
222 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200223}
224
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100225/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200226 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000227 * to the user if mode = 1
228 * returns current device or -1 if no
229 */
230int usb_stor_scan(int mode)
231{
232 unsigned char i;
233 struct usb_device *dev;
234
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100235 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200236 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100237
wdenkaffae2b2002-08-17 09:36:01 +0000238 usb_disable_asynch(1); /* asynch transfer not allowed */
239
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100240 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
241 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100242 usb_dev_desc[i].if_type = IF_TYPE_USB;
243 usb_dev_desc[i].dev = i;
244 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200245 usb_dev_desc[i].target = 0xff;
246 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100247 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530248 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000249 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200250
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100251 usb_max_devs = 0;
252 for (i = 0; i < USB_MAX_DEVICE; i++) {
253 dev = usb_get_dev_index(i); /* get device */
254 USB_STOR_PRINTF("i=%d\n", i);
255 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100256 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100257
258 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200259 /* OK, it's a storage device. Iterate over its LUNs
260 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100261 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200262 int lun, max_lun, start = usb_max_devs;
263
264 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
265 for (lun = 0;
266 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
267 lun++) {
268 usb_dev_desc[usb_max_devs].lun = lun;
269 if (usb_stor_get_info(dev, &usb_stor[start],
270 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000271 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100272 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200273 }
274 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100275 /* if storage device */
276 if (usb_max_devs == USB_MAX_STOR_DEV) {
277 printf("max USB Storage Device reached: %d stopping\n",
278 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000279 break;
280 }
281 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200282
wdenkaffae2b2002-08-17 09:36:01 +0000283 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200284 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100285 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000286 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100287 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000288}
289
290static int usb_stor_irq(struct usb_device *dev)
291{
292 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100293 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000294
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100295 if (us->ip_wanted)
296 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000297 return 0;
298}
299
300
301#ifdef USB_STOR_DEBUG
302
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100303static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000304{
305 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100306 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
307 for (i = 0; i < 12; i++)
308 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000309 printf("\n");
310}
311
312static void display_int_status(unsigned long tmp)
313{
314 printf("Status: %s %s %s %s %s %s %s\n",
315 (tmp & USB_ST_ACTIVE) ? "Active" : "",
316 (tmp & USB_ST_STALLED) ? "Stalled" : "",
317 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
318 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
319 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
320 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
321 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
322}
323#endif
324/***********************************************************************
325 * Data transfer routines
326 ***********************************************************************/
327
328static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
329{
330 int max_size;
331 int this_xfer;
332 int result;
333 int partial;
334 int maxtry;
335 int stat;
336
337 /* determine the maximum packet size for these transfers */
338 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
339
340 /* while we have data left to transfer */
341 while (length) {
342
343 /* calculate how long this will be -- maximum or a remainder */
344 this_xfer = length > max_size ? max_size : length;
345 length -= this_xfer;
346
347 /* setup the retry counter */
348 maxtry = 10;
349
350 /* set up the transfer loop */
351 do {
352 /* transfer the data */
353 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
354 (unsigned int)buf, this_xfer, 11 - maxtry);
355 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100356 this_xfer, &partial,
357 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000358 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
359 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100360 if (us->pusb_dev->status != 0) {
361 /* if we stall, we need to clear it before
362 * we go on
363 */
wdenkaffae2b2002-08-17 09:36:01 +0000364#ifdef USB_STOR_DEBUG
365 display_int_status(us->pusb_dev->status);
366#endif
367 if (us->pusb_dev->status & USB_ST_STALLED) {
368 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
369 stat = us->pusb_dev->status;
370 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100371 us->pusb_dev->status = stat;
372 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200373 USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000374 return 0;
375 }
376 else
377 return result;
378 }
379 if (us->pusb_dev->status & USB_ST_NAK_REC) {
380 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
381 return result;
382 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100383 USB_STOR_PRINTF("bulk transferred with error");
384 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200385 USB_STOR_PRINTF(" %ld, but data ok\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100386 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000387 return 0;
388 }
389 /* if our try counter reaches 0, bail out */
Marek Vasut4b210e82011-10-25 11:39:17 +0200390 USB_STOR_PRINTF(" %ld, data %d\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100391 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000392 if (!maxtry--)
393 return result;
394 }
395 /* update to show what data was transferred */
396 this_xfer -= partial;
397 buf += partial;
398 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100399 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000400 }
401
402 /* if we get here, we're done and successful */
403 return 0;
404}
405
wdenk149dded2003-09-10 18:20:28 +0000406static int usb_stor_BBB_reset(struct us_data *us)
407{
408 int result;
409 unsigned int pipe;
410
411 /*
412 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
413 *
414 * For Reset Recovery the host shall issue in the following order:
415 * a) a Bulk-Only Mass Storage Reset
416 * b) a Clear Feature HALT to the Bulk-In endpoint
417 * c) a Clear Feature HALT to the Bulk-Out endpoint
418 *
419 * This is done in 3 steps.
420 *
421 * If the reset doesn't succeed, the device should be port reset.
422 *
423 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
424 */
425 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100426 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
427 US_BBB_RESET,
428 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
429 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200430
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100431 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000432 USB_STOR_PRINTF("RESET:stall\n");
433 return -1;
434 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200435
wdenk149dded2003-09-10 18:20:28 +0000436 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000437 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200438 USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100439 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000440 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
441 result = usb_clear_halt(us->pusb_dev, pipe);
442 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000443 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200444 USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100445 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000446 /* long wait for reset */
447 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
448 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000449 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200450 USB_STOR_PRINTF("BBB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100451 " clearing OUT endpoint\n", result,
452 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000453 USB_STOR_PRINTF("BBB_reset done\n");
454 return 0;
455}
456
wdenkaffae2b2002-08-17 09:36:01 +0000457/* FIXME: this reset function doesn't really reset the port, and it
458 * should. Actually it should probably do what it's doing here, and
459 * reset the port physically
460 */
461static int usb_stor_CB_reset(struct us_data *us)
462{
463 unsigned char cmd[12];
464 int result;
465
466 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100467 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000468 cmd[0] = SCSI_SEND_DIAG;
469 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100470 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
471 US_CBI_ADSC,
472 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
473 0, us->ifnum, cmd, sizeof(cmd),
474 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000475
476 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000477 mdelay(1500);
Marek Vasut4b210e82011-10-25 11:39:17 +0200478 USB_STOR_PRINTF("CB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100479 " clearing endpoint halt\n", result,
480 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000481 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
482 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
483
484 USB_STOR_PRINTF("CB_reset done\n");
485 return 0;
486}
487
wdenk149dded2003-09-10 18:20:28 +0000488/*
489 * Set up the command for a BBB device. Note that the actual SCSI
490 * command is copied into cbw.CBWCDB.
491 */
492int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
493{
494 int result;
495 int actlen;
496 int dir_in;
497 unsigned int pipe;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530498 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000499
500 dir_in = US_DIRECTION(srb->cmd[0]);
501
502#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100503 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
504 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
505 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000506 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100507 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000508 printf("cmd[%d] %#x ", result, srb->cmd[result]);
509 printf("\n");
510 }
511#endif
512 /* sanity checks */
513 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
514 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
515 return -1;
516 }
517
518 /* always OUT to the ep */
519 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
520
Puneet Saxenaf5766132012-04-03 14:56:06 +0530521 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
522 cbw->dCBWTag = cpu_to_le32(CBWTag++);
523 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
524 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
525 cbw->bCBWLUN = srb->lun;
526 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000527 /* copy the command data into the CBW command data buffer */
528 /* DST SRC LEN!!! */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530529 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
530 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100531 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000532 if (result < 0)
533 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
534 return result;
535}
536
wdenkaffae2b2002-08-17 09:36:01 +0000537/* FIXME: we also need a CBI_command which sets up the completion
538 * interrupt, and waits for it
539 */
540int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
541{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200542 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100543 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000544 unsigned int pipe;
545 unsigned long status;
546
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 retry = 5;
548 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000549
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100550 if (dir_in)
551 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
552 else
553 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
554
555 while (retry--) {
556 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000557#ifdef USB_STOR_DEBUG
558 usb_show_srb(srb);
559#endif
560 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100561 result = usb_control_msg(us->pusb_dev,
562 usb_sndctrlpipe(us->pusb_dev , 0),
563 US_CBI_ADSC,
564 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000565 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100566 srb->cmd, srb->cmdlen,
567 USB_CNTL_TIMEOUT * 5);
568 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
Marek Vasut4b210e82011-10-25 11:39:17 +0200569 " status %lX\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000570 /* check the return code for the command */
571 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100572 if (us->pusb_dev->status & USB_ST_STALLED) {
573 status = us->pusb_dev->status;
574 USB_STOR_PRINTF(" stall during command found,"
575 " clear pipe\n");
576 usb_clear_halt(us->pusb_dev,
577 usb_sndctrlpipe(us->pusb_dev, 0));
578 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000579 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100580 USB_STOR_PRINTF(" error during command %02X"
Marek Vasut4b210e82011-10-25 11:39:17 +0200581 " Stat = %lX\n", srb->cmd[0],
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100582 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000583 return result;
584 }
585 /* transfer the data payload for this command, if one exists*/
586
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100587 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
588 " direction is %s to go 0x%lx\n", result,
589 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000590 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100591 result = us_one_transfer(us, pipe, (char *)srb->pdata,
592 srb->datalen);
593 USB_STOR_PRINTF("CBI attempted to transfer data,"
594 " result is %d status %lX, len %d\n",
595 result, us->pusb_dev->status,
596 us->pusb_dev->act_len);
597 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000598 break;
599 } /* if (srb->datalen) */
600 else
601 break;
602 }
603 /* return result */
604
605 return result;
606}
607
608
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100609int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000610{
611 int timeout;
612
wdenk80885a92004-02-26 23:46:20 +0000613 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100614 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000615 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
616 timeout = 1000;
617 while (timeout--) {
618 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000619 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000620 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000621 }
622 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100623 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000624 us->ip_wanted = 0;
625 return USB_STOR_TRANSPORT_ERROR;
626 }
wdenk80885a92004-02-26 23:46:20 +0000627 USB_STOR_PRINTF
628 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
629 us->ip_data, us->pusb_dev->irq_act_len,
630 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000631 /* UFI gives us ASC and ASCQ, like a request sense */
632 if (us->subclass == US_SC_UFI) {
633 if (srb->cmd[0] == SCSI_REQ_SENSE ||
634 srb->cmd[0] == SCSI_INQUIRY)
635 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000636 else if (us->ip_data)
637 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000638 else
wdenk80885a92004-02-26 23:46:20 +0000639 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000640 }
641 /* otherwise, we interpret the data normally */
642 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000643 case 0x0001:
644 return USB_STOR_TRANSPORT_GOOD;
645 case 0x0002:
646 return USB_STOR_TRANSPORT_FAILED;
647 default:
648 return USB_STOR_TRANSPORT_ERROR;
649 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000650 return USB_STOR_TRANSPORT_ERROR;
651}
652
653#define USB_TRANSPORT_UNKNOWN_RETRY 5
654#define USB_TRANSPORT_NOT_READY_RETRY 10
655
wdenk149dded2003-09-10 18:20:28 +0000656/* clear a stall on an endpoint - special for BBB devices */
657int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
658{
659 int result;
660
661 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100662 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000663 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000665 return result;
666}
667
668int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
669{
670 int result, retry;
671 int dir_in;
672 int actlen, data_actlen;
673 unsigned int pipe, pipein, pipeout;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530674 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000675#ifdef BBB_XPORT_TRACE
676 unsigned char *ptr;
677 int index;
678#endif
679
680 dir_in = US_DIRECTION(srb->cmd[0]);
681
682 /* COMMAND phase */
683 USB_STOR_PRINTF("COMMAND phase\n");
684 result = usb_stor_BBB_comdat(srb, us);
685 if (result < 0) {
686 USB_STOR_PRINTF("failed to send CBW status %ld\n",
687 us->pusb_dev->status);
688 usb_stor_BBB_reset(us);
689 return USB_STOR_TRANSPORT_FAILED;
690 }
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000691 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000692 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
693 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
694 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000695 data_actlen = 0;
696 /* no data, go immediately to the STATUS phase */
697 if (srb->datalen == 0)
698 goto st;
wdenk80885a92004-02-26 23:46:20 +0000699 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000700 if (dir_in)
701 pipe = pipein;
702 else
703 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100704 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
705 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000706 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100707 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000708 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000709 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100710 result = usb_stor_BBB_clear_endpt_stall(us,
711 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000712 if (result >= 0)
713 /* continue on to STATUS phase */
714 goto st;
715 }
716 if (result < 0) {
717 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
718 us->pusb_dev->status);
719 usb_stor_BBB_reset(us);
720 return USB_STOR_TRANSPORT_FAILED;
721 }
722#ifdef BBB_XPORT_TRACE
723 for (index = 0; index < data_actlen; index++)
724 printf("pdata[%d] %#x ", index, srb->pdata[index]);
725 printf("\n");
726#endif
727 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100728st:
wdenk149dded2003-09-10 18:20:28 +0000729 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100730again:
wdenk149dded2003-09-10 18:20:28 +0000731 USB_STOR_PRINTF("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530732 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200733 &actlen, USB_CNTL_TIMEOUT*5);
734
wdenk149dded2003-09-10 18:20:28 +0000735 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100736 if ((result < 0) && (retry < 1) &&
737 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000738 USB_STOR_PRINTF("STATUS:stall\n");
739 /* clear the STALL on the endpoint */
740 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
741 if (result >= 0 && (retry++ < 1))
742 /* do a retry */
743 goto again;
744 }
745 if (result < 0) {
746 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
747 us->pusb_dev->status);
748 usb_stor_BBB_reset(us);
749 return USB_STOR_TRANSPORT_FAILED;
750 }
751#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530752 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000753 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
754 printf("ptr[%d] %#x ", index, ptr[index]);
755 printf("\n");
756#endif
757 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530758 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000759 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
760 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530761 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000762 USB_STOR_PRINTF("!CSWSIGNATURE\n");
763 usb_stor_BBB_reset(us);
764 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530765 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000766 USB_STOR_PRINTF("!Tag\n");
767 usb_stor_BBB_reset(us);
768 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530769 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
wdenk149dded2003-09-10 18:20:28 +0000770 USB_STOR_PRINTF(">PHASE\n");
771 usb_stor_BBB_reset(us);
772 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530773 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
wdenk149dded2003-09-10 18:20:28 +0000774 USB_STOR_PRINTF("=PHASE\n");
775 usb_stor_BBB_reset(us);
776 return USB_STOR_TRANSPORT_FAILED;
777 } else if (data_actlen > srb->datalen) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200778 USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
wdenk149dded2003-09-10 18:20:28 +0000779 data_actlen, srb->datalen);
780 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530781 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
wdenk149dded2003-09-10 18:20:28 +0000782 USB_STOR_PRINTF("FAILED\n");
783 return USB_STOR_TRANSPORT_FAILED;
784 }
785
786 return result;
787}
788
wdenkaffae2b2002-08-17 09:36:01 +0000789int usb_stor_CB_transport(ccb *srb, struct us_data *us)
790{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100791 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000792 ccb *psrb;
793 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100794 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000795
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200796 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100797 status = USB_STOR_TRANSPORT_GOOD;
798 retry = 0;
799 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000800 /* issue the command */
801do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100802 result = usb_stor_CB_comdat(srb, us);
Marek Vasut4b210e82011-10-25 11:39:17 +0200803 USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100804 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000805 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 if (us->protocol == US_PR_CBI) {
807 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000808 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100809 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000810 USB_STOR_PRINTF(" USB CBI Command Error\n");
811 return status;
812 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100813 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
814 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
815 if (!us->ip_data) {
816 /* if the status is good, report it */
817 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000818 USB_STOR_PRINTF(" USB CBI Command Good\n");
819 return status;
820 }
821 }
822 }
823 /* do we have to issue an auto request? */
824 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100825 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200826 USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000827 us->transport_reset(us);
828 return USB_STOR_TRANSPORT_ERROR;
829 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100830 if ((us->protocol == US_PR_CBI) &&
831 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
832 (srb->cmd[0] == SCSI_INQUIRY))) {
833 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000834 USB_STOR_PRINTF("No auto request and good\n");
835 return USB_STOR_TRANSPORT_GOOD;
836 }
837 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100838 memset(&psrb->cmd[0], 0, 12);
839 psrb->cmd[0] = SCSI_REQ_SENSE;
840 psrb->cmd[1] = srb->lun << 5;
841 psrb->cmd[4] = 18;
842 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200843 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100844 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000845 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100846 result = usb_stor_CB_comdat(psrb, us);
847 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000848 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100849 if (us->protocol == US_PR_CBI)
850 status = usb_stor_CBI_get_status(psrb, us);
851
852 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200853 USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100854 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000855 return USB_STOR_TRANSPORT_ERROR;
856 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100857 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
858 srb->sense_buf[0], srb->sense_buf[2],
859 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000860 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100861 if ((srb->sense_buf[2] == 0) &&
862 (srb->sense_buf[12] == 0) &&
863 (srb->sense_buf[13] == 0)) {
864 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000865 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 }
867
wdenkaffae2b2002-08-17 09:36:01 +0000868 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100869 switch (srb->sense_buf[2]) {
870 case 0x01:
871 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000872 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000873 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100874 case 0x02:
875 /* Not Ready */
876 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
877 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
878 " 0x%02X (NOT READY)\n", srb->cmd[0],
879 srb->sense_buf[0], srb->sense_buf[2],
880 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000881 return USB_STOR_TRANSPORT_FAILED;
882 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000883 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000884 goto do_retry;
885 }
886 break;
887 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100888 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
889 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
890 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
891 srb->sense_buf[2], srb->sense_buf[12],
892 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000893 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100894 } else
wdenk149dded2003-09-10 18:20:28 +0000895 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000896 break;
wdenkaffae2b2002-08-17 09:36:01 +0000897 }
898 return USB_STOR_TRANSPORT_FAILED;
899}
900
901
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100902static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000903{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100904 int retry, i;
905 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000906 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100907 memset(&srb->cmd[0], 0, 12);
908 srb->cmd[0] = SCSI_INQUIRY;
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] = 36;
911 srb->datalen = 36;
912 srb->cmdlen = 12;
913 i = ss->transport(srb, ss);
914 USB_STOR_PRINTF("inquiry returns %d\n", i);
915 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000916 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200917 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000918
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100919 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000920 printf("error in inquiry\n");
921 return -1;
922 }
923 return 0;
924}
925
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100926static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000927{
928 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000929
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100930 ptr = (char *)srb->pdata;
931 memset(&srb->cmd[0], 0, 12);
932 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200933 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100934 srb->cmd[4] = 18;
935 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200936 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100937 srb->cmdlen = 12;
938 ss->transport(srb, ss);
939 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
940 srb->sense_buf[2], srb->sense_buf[12],
941 srb->sense_buf[13]);
942 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000943 return 0;
944}
945
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100946static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000947{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200948 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000949
wdenkaffae2b2002-08-17 09:36:01 +0000950 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100951 memset(&srb->cmd[0], 0, 12);
952 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200953 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100954 srb->datalen = 0;
955 srb->cmdlen = 12;
956 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000957 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 usb_request_sense(srb, ss);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000959 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100960 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000961
wdenkaffae2b2002-08-17 09:36:01 +0000962 return -1;
963}
964
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100965static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000966{
967 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100968 /* XXX retries */
969 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000970 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100971 memset(&srb->cmd[0], 0, 12);
972 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200973 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100974 srb->datalen = 8;
975 srb->cmdlen = 12;
976 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000977 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100978 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000979
wdenkaffae2b2002-08-17 09:36:01 +0000980 return -1;
981}
982
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100983static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
984 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000985{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100986 memset(&srb->cmd[0], 0, 12);
987 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200988 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100989 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
990 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
991 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
992 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
993 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
994 srb->cmd[8] = (unsigned char) blocks & 0xff;
995 srb->cmdlen = 12;
996 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
997 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000998}
999
Mahavir Jain127e1082009-11-03 12:22:10 +05301000static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1001 unsigned short blocks)
1002{
1003 memset(&srb->cmd[0], 0, 12);
1004 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001005 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301006 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1007 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1008 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1009 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1010 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1011 srb->cmd[8] = (unsigned char) blocks & 0xff;
1012 srb->cmdlen = 12;
1013 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1014 return ss->transport(srb, ss);
1015}
1016
wdenkaffae2b2002-08-17 09:36:01 +00001017
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001018#ifdef CONFIG_USB_BIN_FIXUP
1019/*
1020 * Some USB storage devices queried for SCSI identification data respond with
1021 * binary strings, which if output to the console freeze the terminal. The
1022 * workaround is to modify the vendor and product strings read from such
1023 * device with proper values (as reported by 'usb info').
1024 *
1025 * Vendor and product length limits are taken from the definition of
1026 * block_dev_desc_t in include/part.h.
1027 */
1028static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1029 unsigned char vendor[],
1030 unsigned char product[]) {
1031 const unsigned char max_vendor_len = 40;
1032 const unsigned char max_product_len = 20;
1033 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001034 strncpy((char *)vendor, "SMSC", max_vendor_len);
1035 strncpy((char *)product, "Flash Media Cntrller",
1036 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001037 }
1038}
1039#endif /* CONFIG_USB_BIN_FIXUP */
1040
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001041unsigned long usb_stor_read(int device, unsigned long blknr,
1042 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001043{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044 unsigned long start, blks, buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001045 unsigned short smallblks;
1046 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001047 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001048 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001049 ccb *srb = &usb_ccb;
1050
1051 if (blkcnt == 0)
1052 return 0;
1053
1054 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001055 /* Setup device */
1056 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1057 dev = NULL;
1058 for (i = 0; i < USB_MAX_DEVICE; i++) {
1059 dev = usb_get_dev_index(i);
1060 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001061 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001062 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001063 break;
1064 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001065 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001066
1067 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001068 srb->lun = usb_dev_desc[device].lun;
1069 buf_addr = (unsigned long)buffer;
1070 start = blknr;
1071 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001072 if (usb_test_unit_ready(srb, ss)) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001073 printf("Device NOT ready\n Request Sense returned %02X %02X"
1074 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1075 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001076 return 0;
1077 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001078
1079 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1080 " buffer %lx\n", device, start, blks, buf_addr);
1081
wdenkaffae2b2002-08-17 09:36:01 +00001082 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001083 /* XXX need some comment here */
1084 retry = 2;
1085 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001086 if (blks > ss->max_xfer_blk)
1087 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001088 else
1089 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001090retry_it:
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001091 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001092 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001093 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1094 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001095 if (usb_read_10(srb, ss, start, smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001096 USB_STOR_PRINTF("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001097 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001098 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001099 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001100 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001101 break;
1102 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001103 start += smallblks;
1104 blks -= smallblks;
1105 buf_addr += srb->datalen;
1106 } while (blks != 0);
1107
1108 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1109 start, smallblks, buf_addr);
1110
wdenkaffae2b2002-08-17 09:36:01 +00001111 usb_disable_asynch(0); /* asynch transfer allowed */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001112 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001113 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001114 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001115}
1116
Mahavir Jain127e1082009-11-03 12:22:10 +05301117unsigned long usb_stor_write(int device, unsigned long blknr,
1118 unsigned long blkcnt, const void *buffer)
1119{
1120 unsigned long start, blks, buf_addr;
1121 unsigned short smallblks;
1122 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001123 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301124 int retry, i;
1125 ccb *srb = &usb_ccb;
1126
1127 if (blkcnt == 0)
1128 return 0;
1129
1130 device &= 0xff;
1131 /* Setup device */
1132 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1133 dev = NULL;
1134 for (i = 0; i < USB_MAX_DEVICE; i++) {
1135 dev = usb_get_dev_index(i);
1136 if (dev == NULL)
1137 return 0;
1138 if (dev->devnum == usb_dev_desc[device].target)
1139 break;
1140 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001141 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301142
1143 usb_disable_asynch(1); /* asynch transfer not allowed */
1144
1145 srb->lun = usb_dev_desc[device].lun;
1146 buf_addr = (unsigned long)buffer;
1147 start = blknr;
1148 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001149 if (usb_test_unit_ready(srb, ss)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301150 printf("Device NOT ready\n Request Sense returned %02X %02X"
1151 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1152 srb->sense_buf[13]);
1153 return 0;
1154 }
1155
1156 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1157 " buffer %lx\n", device, start, blks, buf_addr);
1158
1159 do {
1160 /* If write fails retry for max retry count else
1161 * return with number of blocks written successfully.
1162 */
1163 retry = 2;
1164 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001165 if (blks > ss->max_xfer_blk)
1166 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301167 else
1168 smallblks = (unsigned short) blks;
1169retry_it:
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001170 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301171 usb_show_progress();
1172 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1173 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001174 if (usb_write_10(srb, ss, start, smallblks)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301175 USB_STOR_PRINTF("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001176 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301177 if (retry--)
1178 goto retry_it;
1179 blkcnt -= blks;
1180 break;
1181 }
1182 start += smallblks;
1183 blks -= smallblks;
1184 buf_addr += srb->datalen;
1185 } while (blks != 0);
1186
1187 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1188 start, smallblks, buf_addr);
1189
1190 usb_disable_asynch(0); /* asynch transfer allowed */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001191 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001192 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301193 return blkcnt;
1194
1195}
wdenkaffae2b2002-08-17 09:36:01 +00001196
1197/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001198int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1199 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001200{
Tom Rix8f8bd562009-10-31 12:37:38 -05001201 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001202 int i;
1203 unsigned int flags = 0;
1204
1205 int protocol = 0;
1206 int subclass = 0;
1207
wdenkaffae2b2002-08-17 09:36:01 +00001208 /* let's examine the device now */
1209 iface = &dev->config.if_desc[ifnum];
1210
1211#if 0
1212 /* this is the place to patch some storage devices */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001213 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1214 dev->descriptor.idProduct);
1215
1216 if ((dev->descriptor.idVendor) == 0x066b &&
1217 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001218 USB_STOR_PRINTF("patched for E-USB\n");
1219 protocol = US_PR_CB;
1220 subclass = US_SC_UFI; /* an assumption */
1221 }
1222#endif
1223
1224 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001225 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1226 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1227 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001228 /* if it's not a mass storage, we go no further */
1229 return 0;
1230 }
1231
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001232 memset(ss, 0, sizeof(struct us_data));
1233
wdenkaffae2b2002-08-17 09:36:01 +00001234 /* At this point, we know we've got a live one */
1235 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1236
1237 /* Initialize the us_data structure with some useful info */
1238 ss->flags = flags;
1239 ss->ifnum = ifnum;
1240 ss->pusb_dev = dev;
1241 ss->attention_done = 0;
1242
1243 /* If the device has subclass and protocol, then use that. Otherwise,
1244 * take data from the specific interface.
1245 */
1246 if (subclass) {
1247 ss->subclass = subclass;
1248 ss->protocol = protocol;
1249 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001250 ss->subclass = iface->desc.bInterfaceSubClass;
1251 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001252 }
1253
1254 /* set the handler pointers based on the protocol */
1255 USB_STOR_PRINTF("Transport: ");
1256 switch (ss->protocol) {
1257 case US_PR_CB:
1258 USB_STOR_PRINTF("Control/Bulk\n");
1259 ss->transport = usb_stor_CB_transport;
1260 ss->transport_reset = usb_stor_CB_reset;
1261 break;
1262
1263 case US_PR_CBI:
1264 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1265 ss->transport = usb_stor_CB_transport;
1266 ss->transport_reset = usb_stor_CB_reset;
1267 break;
wdenk149dded2003-09-10 18:20:28 +00001268 case US_PR_BULK:
1269 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1270 ss->transport = usb_stor_BBB_transport;
1271 ss->transport_reset = usb_stor_BBB_reset;
1272 break;
wdenkaffae2b2002-08-17 09:36:01 +00001273 default:
wdenk80885a92004-02-26 23:46:20 +00001274 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001275 return 0;
1276 break;
1277 }
1278
1279 /*
1280 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1281 * An optional interrupt is OK (necessary for CBI protocol).
1282 * We will ignore any others.
1283 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001284 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001285 /* is it an BULK endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001286 if ((iface->ep_desc[i].bmAttributes &
1287 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001288 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1289 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1290 USB_ENDPOINT_NUMBER_MASK;
1291 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001292 ss->ep_out =
1293 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001294 USB_ENDPOINT_NUMBER_MASK;
1295 }
1296
1297 /* is it an interrupt endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001298 if ((iface->ep_desc[i].bmAttributes &
1299 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001300 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1301 USB_ENDPOINT_NUMBER_MASK;
1302 ss->irqinterval = iface->ep_desc[i].bInterval;
1303 }
1304 }
1305 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1306 ss->ep_in, ss->ep_out, ss->ep_int);
1307
1308 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001309 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001310 !ss->ep_in || !ss->ep_out ||
1311 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1312 USB_STOR_PRINTF("Problems with device\n");
1313 return 0;
1314 }
1315 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001316 /* We only handle certain protocols. Currently, these are
1317 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001318 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001319 */
wdenk80885a92004-02-26 23:46:20 +00001320 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1321 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001322 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001323 return 0;
1324 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001325 if (ss->ep_int) {
1326 /* we had found an interrupt endpoint, prepare irq pipe
1327 * set up the IRQ pipe and handler
1328 */
wdenkaffae2b2002-08-17 09:36:01 +00001329 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1330 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1331 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001332 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001333 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001334 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001335 return 1;
1336}
1337
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001338int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1339 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001340{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001341 unsigned char perq, modi;
Puneet Saxenaf5766132012-04-03 14:56:06 +05301342 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1343 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001344 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001345 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001346
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001347 pccb->pdata = usb_stor_buf;
1348
1349 dev_desc->target = dev->devnum;
1350 pccb->lun = dev_desc->lun;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001351 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001352
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001353 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001354 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001355
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001356 perq = usb_stor_buf[0];
1357 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001358
1359 if ((perq & 0x1f) == 0x1f) {
1360 /* skip unknown devices */
1361 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001362 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001363 if ((modi&0x80) == 0x80) {
1364 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001365 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001366 }
Puneet Saxenaf5766132012-04-03 14:56:06 +05301367 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1368 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1369 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001370 dev_desc->vendor[8] = 0;
1371 dev_desc->product[16] = 0;
1372 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001373#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001374 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1375 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001376#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001377 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1378 usb_stor_buf[3]);
1379 if (usb_test_unit_ready(pccb, ss)) {
1380 printf("Device NOT ready\n"
1381 " Request Sense returned %02X %02X %02X\n",
1382 pccb->sense_buf[2], pccb->sense_buf[12],
1383 pccb->sense_buf[13]);
1384 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001385 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001386 return 1;
1387 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001388 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001389 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001390 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001391 memset(pccb->pdata, 0, 8);
1392 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001393 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001394 cap[0] = 2880;
1395 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001396 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001397 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1398 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001399#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001400 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1401 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001402#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001403 cap[0] = cpu_to_be32(cap[0]);
1404 cap[1] = cpu_to_be32(cap[1]);
1405
wdenk149dded2003-09-10 18:20:28 +00001406 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001407 cap[0] += 1;
1408 capacity = &cap[0];
1409 blksz = &cap[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001410 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1411 *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001412 dev_desc->lba = *capacity;
1413 dev_desc->blksz = *blksz;
1414 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001415 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1416 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001417
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001418 /*
1419 * The U-Boot EHCI driver cannot handle more than 4096 * 5 bytes in a
1420 * transfer without running itself out of qt_buffers.
1421 */
1422 ss->max_xfer_blk = (4096 * 5) / dev_desc->blksz;
1423
wdenkaffae2b2002-08-17 09:36:01 +00001424 init_part(dev_desc);
1425
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001426 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001427 return 1;
1428}