blob: d9a2585d5800af782698e784f8c108f5e22f5133 [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
wdenkaffae2b2002-08-17 09:36:01 +000012 *
wdenkde887eb2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundelf1b3f2b2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenkde887eb2003-09-10 18:20:28 +000015 *
Wolfgang Denk6a3d6b02005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenkde887eb2003-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
wdenk5f495752004-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 */
wdenkde887eb2003-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.
wdenkde887eb2003-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 Eggers4e0e8d02008-05-21 22:12:00 +020053#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000054#include <asm/processor.h>
55
Grant Likelyffc2dd72007-02-20 09:04:34 +010056#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000057#include <usb.h>
58
wdenk5f495752004-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 Vasut772b6882011-10-25 11:39:16 +020063#define USB_BLK_DEBUG 1
wdenkaffae2b2002-08-17 09:36:01 +000064#else
Marek Vasut772b6882011-10-25 11:39:16 +020065#define USB_BLK_DEBUG 0
wdenkaffae2b2002-08-17 09:36:01 +000066#endif
67
Marek Vasut772b6882011-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 Frysinger165522b2010-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
82static unsigned char usb_stor_buf[512];
83static ccb usb_ccb;
84
85/*
86 * CBI style
87 */
88
89#define US_CBI_ADSC 0
90
wdenkde887eb2003-09-10 18:20:28 +000091/*
92 * BULK only
93 */
94#define US_BBB_RESET 0xff
95#define US_BBB_GET_MAX_LUN 0xfe
96
97/* Command Block Wrapper */
98typedef struct {
99 __u32 dCBWSignature;
100# define CBWSIGNATURE 0x43425355
101 __u32 dCBWTag;
102 __u32 dCBWDataTransferLength;
103 __u8 bCBWFlags;
104# define CBWFLAGS_OUT 0x00
105# define CBWFLAGS_IN 0x80
106 __u8 bCBWLUN;
107 __u8 bCDBLength;
108# define CBWCDBLENGTH 16
109 __u8 CBWCDB[CBWCDBLENGTH];
110} umass_bbb_cbw_t;
wdenk5f495752004-02-26 23:46:20 +0000111#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchi956a4352008-12-10 15:52:06 +0100112static __u32 CBWTag;
wdenkde887eb2003-09-10 18:20:28 +0000113
114/* Command Status Wrapper */
115typedef struct {
116 __u32 dCSWSignature;
117# define CSWSIGNATURE 0x53425355
118 __u32 dCSWTag;
119 __u32 dCSWDataResidue;
120 __u8 bCSWStatus;
121# define CSWSTATUS_GOOD 0x0
wdenk5f495752004-02-26 23:46:20 +0000122# define CSWSTATUS_FAILED 0x1
wdenkde887eb2003-09-10 18:20:28 +0000123# define CSWSTATUS_PHASE 0x2
124} umass_bbb_csw_t;
wdenk5f495752004-02-26 23:46:20 +0000125#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000126
127#define USB_MAX_STOR_DEV 5
Michael Trimarchi956a4352008-12-10 15:52:06 +0100128static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000129
130static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
131
132struct us_data;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100133typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
134typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000135
136struct us_data {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100137 struct usb_device *pusb_dev; /* this usb_device */
138
139 unsigned int flags; /* from filter initially */
140 unsigned char ifnum; /* interface number */
141 unsigned char ep_in; /* in endpoint */
142 unsigned char ep_out; /* out ....... */
143 unsigned char ep_int; /* interrupt . */
144 unsigned char subclass; /* as in overview */
145 unsigned char protocol; /* .............. */
146 unsigned char attention_done; /* force attn on first cmd */
147 unsigned short ip_data; /* interrupt data */
148 int action; /* what to do */
149 int ip_wanted; /* needed */
150 int *irq_handle; /* for USB int requests */
151 unsigned int irqpipe; /* pipe for release_irq */
152 unsigned char irqmaxp; /* max packed for irq Pipe */
153 unsigned char irqinterval; /* Intervall for IRQ Pipe */
154 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
wdenk5f495752004-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 Trimarchi956a4352008-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 Jaind43a0b82009-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 McClintock6252b4f2011-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. Heino300ea512010-03-12 15:46:56 +0200180 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000181}
Matthew McClintock6252b4f2011-05-24 05:31:19 +0000182#endif
wdenkaffae2b2002-08-17 09:36:01 +0000183
184void usb_show_progress(void)
185{
Wolfgang Denk660e9a42010-07-19 11:36:59 +0200186 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000187}
188
Michael Trimarchi956a4352008-12-10 15:52:06 +0100189/*******************************************************************************
Wolfgang Denkc7a4f7d2005-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 Vaichas7ede1862008-03-25 12:09:07 +1100193int usb_stor_info(void)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200194{
195 int i;
196
Aras Vaichas7ede1862008-03-25 12:09:07 +1100197 if (usb_max_devs > 0) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200198 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100199 printf(" Device %d: ", i);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200200 dev_print(&usb_dev_desc[i]);
201 }
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100202 return 0;
Aras Vaichas7ede1862008-03-25 12:09:07 +1100203 }
Wolfgang Denk35f734f2008-04-13 09:59:26 -0700204
Markus Klotzbuecher8e2a4862008-03-26 18:26:43 +0100205 printf("No storage devices, perhaps not 'usb start'ed..?\n");
206 return 1;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200207}
208
Ludovic Courtès134396c2010-10-05 22:04:26 +0200209static unsigned int usb_get_max_lun(struct us_data *us)
210{
211 int len;
212 unsigned char result;
213 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,
218 &result, sizeof(result),
219 USB_CNTL_TIMEOUT * 5);
220 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
221 len, (int) result);
222 return (len > 0) ? result : 0;
223}
224
Michael Trimarchi956a4352008-12-10 15:52:06 +0100225/*******************************************************************************
Wolfgang Denkc7a4f7d2005-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
wdenkde887eb2003-09-10 18:20:28 +0000235 /* GJ */
236 memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
237
Michael Trimarchi956a4352008-12-10 15:52:06 +0100238 if (mode == 1)
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200239 printf(" scanning bus for storage devices... ");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100240
wdenkaffae2b2002-08-17 09:36:01 +0000241 usb_disable_asynch(1); /* asynch transfer not allowed */
242
Michael Trimarchi956a4352008-12-10 15:52:06 +0100243 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
244 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchi956a4352008-12-10 15:52:06 +0100245 usb_dev_desc[i].if_type = IF_TYPE_USB;
246 usb_dev_desc[i].dev = i;
247 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denk1896bf12010-07-19 11:36:56 +0200248 usb_dev_desc[i].target = 0xff;
249 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100250 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jaind43a0b82009-11-03 12:22:10 +0530251 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000252 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200253
Michael Trimarchi956a4352008-12-10 15:52:06 +0100254 usb_max_devs = 0;
255 for (i = 0; i < USB_MAX_DEVICE; i++) {
256 dev = usb_get_dev_index(i); /* get device */
257 USB_STOR_PRINTF("i=%d\n", i);
258 if (dev == NULL)
Loïc Minier5d0569a2011-02-03 22:04:26 +0100259 break; /* no more devices available */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100260
261 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès134396c2010-10-05 22:04:26 +0200262 /* OK, it's a storage device. Iterate over its LUNs
263 * and populate `usb_dev_desc'.
Michael Trimarchi956a4352008-12-10 15:52:06 +0100264 */
Ludovic Courtès134396c2010-10-05 22:04:26 +0200265 int lun, max_lun, start = usb_max_devs;
266
267 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
268 for (lun = 0;
269 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
270 lun++) {
271 usb_dev_desc[usb_max_devs].lun = lun;
272 if (usb_stor_get_info(dev, &usb_stor[start],
273 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000274 usb_max_devs++;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100275 }
Ludovic Courtès134396c2010-10-05 22:04:26 +0200276 }
277 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100278 /* if storage device */
279 if (usb_max_devs == USB_MAX_STOR_DEV) {
280 printf("max USB Storage Device reached: %d stopping\n",
281 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000282 break;
283 }
284 } /* for */
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200285
wdenkaffae2b2002-08-17 09:36:01 +0000286 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200287 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100288 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000289 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100290 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000291}
292
293static int usb_stor_irq(struct usb_device *dev)
294{
295 struct us_data *us;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100296 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000297
Michael Trimarchi956a4352008-12-10 15:52:06 +0100298 if (us->ip_wanted)
299 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000300 return 0;
301}
302
303
304#ifdef USB_STOR_DEBUG
305
Michael Trimarchi956a4352008-12-10 15:52:06 +0100306static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000307{
308 int i;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100309 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
310 for (i = 0; i < 12; i++)
311 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000312 printf("\n");
313}
314
315static void display_int_status(unsigned long tmp)
316{
317 printf("Status: %s %s %s %s %s %s %s\n",
318 (tmp & USB_ST_ACTIVE) ? "Active" : "",
319 (tmp & USB_ST_STALLED) ? "Stalled" : "",
320 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
321 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
322 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
323 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
324 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
325}
326#endif
327/***********************************************************************
328 * Data transfer routines
329 ***********************************************************************/
330
331static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
332{
333 int max_size;
334 int this_xfer;
335 int result;
336 int partial;
337 int maxtry;
338 int stat;
339
340 /* determine the maximum packet size for these transfers */
341 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
342
343 /* while we have data left to transfer */
344 while (length) {
345
346 /* calculate how long this will be -- maximum or a remainder */
347 this_xfer = length > max_size ? max_size : length;
348 length -= this_xfer;
349
350 /* setup the retry counter */
351 maxtry = 10;
352
353 /* set up the transfer loop */
354 do {
355 /* transfer the data */
356 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
357 (unsigned int)buf, this_xfer, 11 - maxtry);
358 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100359 this_xfer, &partial,
360 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000361 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
362 result, partial, this_xfer);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100363 if (us->pusb_dev->status != 0) {
364 /* if we stall, we need to clear it before
365 * we go on
366 */
wdenkaffae2b2002-08-17 09:36:01 +0000367#ifdef USB_STOR_DEBUG
368 display_int_status(us->pusb_dev->status);
369#endif
370 if (us->pusb_dev->status & USB_ST_STALLED) {
371 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
372 stat = us->pusb_dev->status;
373 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100374 us->pusb_dev->status = stat;
375 if (this_xfer == partial) {
Marek Vasut0f79fc32011-10-25 11:39:17 +0200376 USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000377 return 0;
378 }
379 else
380 return result;
381 }
382 if (us->pusb_dev->status & USB_ST_NAK_REC) {
383 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
384 return result;
385 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100386 USB_STOR_PRINTF("bulk transferred with error");
387 if (this_xfer == partial) {
Marek Vasut0f79fc32011-10-25 11:39:17 +0200388 USB_STOR_PRINTF(" %ld, but data ok\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100389 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000390 return 0;
391 }
392 /* if our try counter reaches 0, bail out */
Marek Vasut0f79fc32011-10-25 11:39:17 +0200393 USB_STOR_PRINTF(" %ld, data %d\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100394 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000395 if (!maxtry--)
396 return result;
397 }
398 /* update to show what data was transferred */
399 this_xfer -= partial;
400 buf += partial;
401 /* continue until this transfer is done */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100402 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000403 }
404
405 /* if we get here, we're done and successful */
406 return 0;
407}
408
wdenkde887eb2003-09-10 18:20:28 +0000409static int usb_stor_BBB_reset(struct us_data *us)
410{
411 int result;
412 unsigned int pipe;
413
414 /*
415 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
416 *
417 * For Reset Recovery the host shall issue in the following order:
418 * a) a Bulk-Only Mass Storage Reset
419 * b) a Clear Feature HALT to the Bulk-In endpoint
420 * c) a Clear Feature HALT to the Bulk-Out endpoint
421 *
422 * This is done in 3 steps.
423 *
424 * If the reset doesn't succeed, the device should be port reset.
425 *
426 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
427 */
428 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100429 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
430 US_BBB_RESET,
431 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
432 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200433
Michael Trimarchi956a4352008-12-10 15:52:06 +0100434 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenkde887eb2003-09-10 18:20:28 +0000435 USB_STOR_PRINTF("RESET:stall\n");
436 return -1;
437 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200438
wdenkde887eb2003-09-10 18:20:28 +0000439 /* long wait for reset */
440 wait_ms(150);
Marek Vasut0f79fc32011-10-25 11:39:17 +0200441 USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100442 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000443 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
444 result = usb_clear_halt(us->pusb_dev, pipe);
445 /* long wait for reset */
446 wait_ms(150);
Marek Vasut0f79fc32011-10-25 11:39:17 +0200447 USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100448 result, us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000449 /* long wait for reset */
450 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
451 result = usb_clear_halt(us->pusb_dev, pipe);
452 wait_ms(150);
Marek Vasut0f79fc32011-10-25 11:39:17 +0200453 USB_STOR_PRINTF("BBB_reset result %d: status %lX"
Michael Trimarchi956a4352008-12-10 15:52:06 +0100454 " clearing OUT endpoint\n", result,
455 us->pusb_dev->status);
wdenkde887eb2003-09-10 18:20:28 +0000456 USB_STOR_PRINTF("BBB_reset done\n");
457 return 0;
458}
459
wdenkaffae2b2002-08-17 09:36:01 +0000460/* FIXME: this reset function doesn't really reset the port, and it
461 * should. Actually it should probably do what it's doing here, and
462 * reset the port physically
463 */
464static int usb_stor_CB_reset(struct us_data *us)
465{
466 unsigned char cmd[12];
467 int result;
468
469 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +0100470 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000471 cmd[0] = SCSI_SEND_DIAG;
472 cmd[1] = 4;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100473 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
474 US_CBI_ADSC,
475 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
476 0, us->ifnum, cmd, sizeof(cmd),
477 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000478
479 /* long wait for reset */
480 wait_ms(1500);
Marek Vasut0f79fc32011-10-25 11:39:17 +0200481 USB_STOR_PRINTF("CB_reset result %d: status %lX"
Michael Trimarchi956a4352008-12-10 15:52:06 +0100482 " clearing endpoint halt\n", result,
483 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000484 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
485 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
486
487 USB_STOR_PRINTF("CB_reset done\n");
488 return 0;
489}
490
wdenkde887eb2003-09-10 18:20:28 +0000491/*
492 * Set up the command for a BBB device. Note that the actual SCSI
493 * command is copied into cbw.CBWCDB.
494 */
495int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
496{
497 int result;
498 int actlen;
499 int dir_in;
500 unsigned int pipe;
501 umass_bbb_cbw_t cbw;
502
503 dir_in = US_DIRECTION(srb->cmd[0]);
504
505#ifdef BBB_COMDAT_TRACE
Michael Trimarchi956a4352008-12-10 15:52:06 +0100506 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
507 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
508 srb->pdata);
wdenkde887eb2003-09-10 18:20:28 +0000509 if (srb->cmdlen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100510 for (result = 0; result < srb->cmdlen; result++)
wdenkde887eb2003-09-10 18:20:28 +0000511 printf("cmd[%d] %#x ", result, srb->cmd[result]);
512 printf("\n");
513 }
514#endif
515 /* sanity checks */
516 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
517 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
518 return -1;
519 }
520
521 /* always OUT to the ep */
522 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
523
Christian Eggers4e0e8d02008-05-21 22:12:00 +0200524 cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
525 cbw.dCBWTag = cpu_to_le32(CBWTag++);
526 cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100527 cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
wdenkde887eb2003-09-10 18:20:28 +0000528 cbw.bCBWLUN = srb->lun;
529 cbw.bCDBLength = srb->cmdlen;
530 /* copy the command data into the CBW command data buffer */
531 /* DST SRC LEN!!! */
532 memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
Michael Trimarchi956a4352008-12-10 15:52:06 +0100533 result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
534 &actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000535 if (result < 0)
536 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
537 return result;
538}
539
wdenkaffae2b2002-08-17 09:36:01 +0000540/* FIXME: we also need a CBI_command which sets up the completion
541 * interrupt, and waits for it
542 */
543int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
544{
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200545 int result = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100546 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000547 unsigned int pipe;
548 unsigned long status;
549
Michael Trimarchi956a4352008-12-10 15:52:06 +0100550 retry = 5;
551 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000552
Michael Trimarchi956a4352008-12-10 15:52:06 +0100553 if (dir_in)
554 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
555 else
556 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
557
558 while (retry--) {
559 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000560#ifdef USB_STOR_DEBUG
561 usb_show_srb(srb);
562#endif
563 /* let's send the command via the control pipe */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100564 result = usb_control_msg(us->pusb_dev,
565 usb_sndctrlpipe(us->pusb_dev , 0),
566 US_CBI_ADSC,
567 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000568 0, us->ifnum,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100569 srb->cmd, srb->cmdlen,
570 USB_CNTL_TIMEOUT * 5);
571 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
Marek Vasut0f79fc32011-10-25 11:39:17 +0200572 " status %lX\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000573 /* check the return code for the command */
574 if (result < 0) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100575 if (us->pusb_dev->status & USB_ST_STALLED) {
576 status = us->pusb_dev->status;
577 USB_STOR_PRINTF(" stall during command found,"
578 " clear pipe\n");
579 usb_clear_halt(us->pusb_dev,
580 usb_sndctrlpipe(us->pusb_dev, 0));
581 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000582 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100583 USB_STOR_PRINTF(" error during command %02X"
Marek Vasut0f79fc32011-10-25 11:39:17 +0200584 " Stat = %lX\n", srb->cmd[0],
Michael Trimarchi956a4352008-12-10 15:52:06 +0100585 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000586 return result;
587 }
588 /* transfer the data payload for this command, if one exists*/
589
Michael Trimarchi956a4352008-12-10 15:52:06 +0100590 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
591 " direction is %s to go 0x%lx\n", result,
592 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000593 if (srb->datalen) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100594 result = us_one_transfer(us, pipe, (char *)srb->pdata,
595 srb->datalen);
596 USB_STOR_PRINTF("CBI attempted to transfer data,"
597 " result is %d status %lX, len %d\n",
598 result, us->pusb_dev->status,
599 us->pusb_dev->act_len);
600 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000601 break;
602 } /* if (srb->datalen) */
603 else
604 break;
605 }
606 /* return result */
607
608 return result;
609}
610
611
Michael Trimarchi956a4352008-12-10 15:52:06 +0100612int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000613{
614 int timeout;
615
wdenk5f495752004-02-26 23:46:20 +0000616 us->ip_wanted = 1;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100617 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk5f495752004-02-26 23:46:20 +0000618 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
619 timeout = 1000;
620 while (timeout--) {
621 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000622 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100623 wait_ms(10);
wdenkaffae2b2002-08-17 09:36:01 +0000624 }
625 if (us->ip_wanted) {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100626 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000627 us->ip_wanted = 0;
628 return USB_STOR_TRANSPORT_ERROR;
629 }
wdenk5f495752004-02-26 23:46:20 +0000630 USB_STOR_PRINTF
631 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
632 us->ip_data, us->pusb_dev->irq_act_len,
633 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000634 /* UFI gives us ASC and ASCQ, like a request sense */
635 if (us->subclass == US_SC_UFI) {
636 if (srb->cmd[0] == SCSI_REQ_SENSE ||
637 srb->cmd[0] == SCSI_INQUIRY)
638 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk5f495752004-02-26 23:46:20 +0000639 else if (us->ip_data)
640 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000641 else
wdenk5f495752004-02-26 23:46:20 +0000642 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000643 }
644 /* otherwise, we interpret the data normally */
645 switch (us->ip_data) {
wdenk5f495752004-02-26 23:46:20 +0000646 case 0x0001:
647 return USB_STOR_TRANSPORT_GOOD;
648 case 0x0002:
649 return USB_STOR_TRANSPORT_FAILED;
650 default:
651 return USB_STOR_TRANSPORT_ERROR;
652 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000653 return USB_STOR_TRANSPORT_ERROR;
654}
655
656#define USB_TRANSPORT_UNKNOWN_RETRY 5
657#define USB_TRANSPORT_NOT_READY_RETRY 10
658
wdenkde887eb2003-09-10 18:20:28 +0000659/* clear a stall on an endpoint - special for BBB devices */
660int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
661{
662 int result;
663
664 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100665 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenkde887eb2003-09-10 18:20:28 +0000666 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchi956a4352008-12-10 15:52:06 +0100667 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000668 return result;
669}
670
671int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
672{
673 int result, retry;
674 int dir_in;
675 int actlen, data_actlen;
676 unsigned int pipe, pipein, pipeout;
677 umass_bbb_csw_t csw;
678#ifdef BBB_XPORT_TRACE
679 unsigned char *ptr;
680 int index;
681#endif
682
683 dir_in = US_DIRECTION(srb->cmd[0]);
684
685 /* COMMAND phase */
686 USB_STOR_PRINTF("COMMAND phase\n");
687 result = usb_stor_BBB_comdat(srb, us);
688 if (result < 0) {
689 USB_STOR_PRINTF("failed to send CBW status %ld\n",
690 us->pusb_dev->status);
691 usb_stor_BBB_reset(us);
692 return USB_STOR_TRANSPORT_FAILED;
693 }
694 wait_ms(5);
695 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
696 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
697 /* DATA phase + error handling */
wdenkde887eb2003-09-10 18:20:28 +0000698 data_actlen = 0;
699 /* no data, go immediately to the STATUS phase */
700 if (srb->datalen == 0)
701 goto st;
wdenk5f495752004-02-26 23:46:20 +0000702 USB_STOR_PRINTF("DATA phase\n");
wdenkde887eb2003-09-10 18:20:28 +0000703 if (dir_in)
704 pipe = pipein;
705 else
706 pipe = pipeout;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100707 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
708 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenkde887eb2003-09-10 18:20:28 +0000709 /* special handling of STALL in DATA phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100710 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk934c4f82003-09-11 19:48:06 +0000711 USB_STOR_PRINTF("DATA:stall\n");
wdenkde887eb2003-09-10 18:20:28 +0000712 /* clear the STALL on the endpoint */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100713 result = usb_stor_BBB_clear_endpt_stall(us,
714 dir_in ? us->ep_in : us->ep_out);
wdenkde887eb2003-09-10 18:20:28 +0000715 if (result >= 0)
716 /* continue on to STATUS phase */
717 goto st;
718 }
719 if (result < 0) {
720 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
721 us->pusb_dev->status);
722 usb_stor_BBB_reset(us);
723 return USB_STOR_TRANSPORT_FAILED;
724 }
725#ifdef BBB_XPORT_TRACE
726 for (index = 0; index < data_actlen; index++)
727 printf("pdata[%d] %#x ", index, srb->pdata[index]);
728 printf("\n");
729#endif
730 /* STATUS phase + error handling */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100731st:
wdenkde887eb2003-09-10 18:20:28 +0000732 retry = 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100733again:
wdenkde887eb2003-09-10 18:20:28 +0000734 USB_STOR_PRINTF("STATUS phase\n");
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +0200735 result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200736 &actlen, USB_CNTL_TIMEOUT*5);
737
wdenkde887eb2003-09-10 18:20:28 +0000738 /* special handling of STALL in STATUS phase */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100739 if ((result < 0) && (retry < 1) &&
740 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenkde887eb2003-09-10 18:20:28 +0000741 USB_STOR_PRINTF("STATUS:stall\n");
742 /* clear the STALL on the endpoint */
743 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
744 if (result >= 0 && (retry++ < 1))
745 /* do a retry */
746 goto again;
747 }
748 if (result < 0) {
749 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
750 us->pusb_dev->status);
751 usb_stor_BBB_reset(us);
752 return USB_STOR_TRANSPORT_FAILED;
753 }
754#ifdef BBB_XPORT_TRACE
755 ptr = (unsigned char *)&csw;
756 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
757 printf("ptr[%d] %#x ", index, ptr[index]);
758 printf("\n");
759#endif
760 /* misuse pipe to get the residue */
Christian Eggers4e0e8d02008-05-21 22:12:00 +0200761 pipe = le32_to_cpu(csw.dCSWDataResidue);
wdenkde887eb2003-09-10 18:20:28 +0000762 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
763 pipe = srb->datalen - data_actlen;
Christian Eggers4e0e8d02008-05-21 22:12:00 +0200764 if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
wdenkde887eb2003-09-10 18:20:28 +0000765 USB_STOR_PRINTF("!CSWSIGNATURE\n");
766 usb_stor_BBB_reset(us);
767 return USB_STOR_TRANSPORT_FAILED;
Christian Eggers4e0e8d02008-05-21 22:12:00 +0200768 } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
wdenkde887eb2003-09-10 18:20:28 +0000769 USB_STOR_PRINTF("!Tag\n");
770 usb_stor_BBB_reset(us);
771 return USB_STOR_TRANSPORT_FAILED;
772 } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
773 USB_STOR_PRINTF(">PHASE\n");
774 usb_stor_BBB_reset(us);
775 return USB_STOR_TRANSPORT_FAILED;
776 } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
777 USB_STOR_PRINTF("=PHASE\n");
778 usb_stor_BBB_reset(us);
779 return USB_STOR_TRANSPORT_FAILED;
780 } else if (data_actlen > srb->datalen) {
Marek Vasut0f79fc32011-10-25 11:39:17 +0200781 USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
wdenkde887eb2003-09-10 18:20:28 +0000782 data_actlen, srb->datalen);
783 return USB_STOR_TRANSPORT_FAILED;
784 } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
785 USB_STOR_PRINTF("FAILED\n");
786 return USB_STOR_TRANSPORT_FAILED;
787 }
788
789 return result;
790}
791
wdenkaffae2b2002-08-17 09:36:01 +0000792int usb_stor_CB_transport(ccb *srb, struct us_data *us)
793{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100794 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000795 ccb *psrb;
796 ccb reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100797 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000798
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200799 psrb = &reqsrb;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100800 status = USB_STOR_TRANSPORT_GOOD;
801 retry = 0;
802 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000803 /* issue the command */
804do_retry:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100805 result = usb_stor_CB_comdat(srb, us);
Marek Vasut0f79fc32011-10-25 11:39:17 +0200806 USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100807 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000808 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100809 if (us->protocol == US_PR_CBI) {
810 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000811 /* if the status is error, report it */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100812 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000813 USB_STOR_PRINTF(" USB CBI Command Error\n");
814 return status;
815 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100816 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
817 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
818 if (!us->ip_data) {
819 /* if the status is good, report it */
820 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000821 USB_STOR_PRINTF(" USB CBI Command Good\n");
822 return status;
823 }
824 }
825 }
826 /* do we have to issue an auto request? */
827 /* HERE we have to check the result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100828 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut0f79fc32011-10-25 11:39:17 +0200829 USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000830 us->transport_reset(us);
831 return USB_STOR_TRANSPORT_ERROR;
832 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100833 if ((us->protocol == US_PR_CBI) &&
834 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
835 (srb->cmd[0] == SCSI_INQUIRY))) {
836 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000837 USB_STOR_PRINTF("No auto request and good\n");
838 return USB_STOR_TRANSPORT_GOOD;
839 }
840 /* issue an request_sense */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100841 memset(&psrb->cmd[0], 0, 12);
842 psrb->cmd[0] = SCSI_REQ_SENSE;
843 psrb->cmd[1] = srb->lun << 5;
844 psrb->cmd[4] = 18;
845 psrb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200846 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100847 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000848 /* issue the command */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100849 result = usb_stor_CB_comdat(psrb, us);
850 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000851 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100852 if (us->protocol == US_PR_CBI)
853 status = usb_stor_CBI_get_status(psrb, us);
854
855 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut0f79fc32011-10-25 11:39:17 +0200856 USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
Michael Trimarchi956a4352008-12-10 15:52:06 +0100857 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000858 return USB_STOR_TRANSPORT_ERROR;
859 }
Michael Trimarchi956a4352008-12-10 15:52:06 +0100860 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
861 srb->sense_buf[0], srb->sense_buf[2],
862 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000863 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100864 if ((srb->sense_buf[2] == 0) &&
865 (srb->sense_buf[12] == 0) &&
866 (srb->sense_buf[13] == 0)) {
867 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000868 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100869 }
870
wdenkaffae2b2002-08-17 09:36:01 +0000871 /* Check the auto request result */
Michael Trimarchi956a4352008-12-10 15:52:06 +0100872 switch (srb->sense_buf[2]) {
873 case 0x01:
874 /* Recovered Error */
wdenkde887eb2003-09-10 18:20:28 +0000875 return USB_STOR_TRANSPORT_GOOD;
wdenk5f495752004-02-26 23:46:20 +0000876 break;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100877 case 0x02:
878 /* Not Ready */
879 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
880 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
881 " 0x%02X (NOT READY)\n", srb->cmd[0],
882 srb->sense_buf[0], srb->sense_buf[2],
883 srb->sense_buf[12], srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000884 return USB_STOR_TRANSPORT_FAILED;
885 } else {
886 wait_ms(100);
887 goto do_retry;
888 }
889 break;
890 default:
Michael Trimarchi956a4352008-12-10 15:52:06 +0100891 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
892 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
893 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
894 srb->sense_buf[2], srb->sense_buf[12],
895 srb->sense_buf[13]);
wdenkde887eb2003-09-10 18:20:28 +0000896 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100897 } else
wdenkde887eb2003-09-10 18:20:28 +0000898 goto do_retry;
wdenkde887eb2003-09-10 18:20:28 +0000899 break;
wdenkaffae2b2002-08-17 09:36:01 +0000900 }
901 return USB_STOR_TRANSPORT_FAILED;
902}
903
904
Michael Trimarchi956a4352008-12-10 15:52:06 +0100905static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000906{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100907 int retry, i;
908 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000909 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100910 memset(&srb->cmd[0], 0, 12);
911 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200912 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100913 srb->cmd[4] = 36;
914 srb->datalen = 36;
915 srb->cmdlen = 12;
916 i = ss->transport(srb, ss);
917 USB_STOR_PRINTF("inquiry returns %d\n", i);
918 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000919 break;
Kim B. Heino3d42b8a2010-03-12 10:07:00 +0200920 } while (--retry);
wdenkde887eb2003-09-10 18:20:28 +0000921
Michael Trimarchi956a4352008-12-10 15:52:06 +0100922 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000923 printf("error in inquiry\n");
924 return -1;
925 }
926 return 0;
927}
928
Michael Trimarchi956a4352008-12-10 15:52:06 +0100929static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000930{
931 char *ptr;
wdenk5f495752004-02-26 23:46:20 +0000932
Michael Trimarchi956a4352008-12-10 15:52:06 +0100933 ptr = (char *)srb->pdata;
934 memset(&srb->cmd[0], 0, 12);
935 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200936 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100937 srb->cmd[4] = 18;
938 srb->datalen = 18;
Wolfgang Denkdc770c72008-07-14 15:19:07 +0200939 srb->pdata = &srb->sense_buf[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +0100940 srb->cmdlen = 12;
941 ss->transport(srb, ss);
942 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
943 srb->sense_buf[2], srb->sense_buf[12],
944 srb->sense_buf[13]);
945 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000946 return 0;
947}
948
Michael Trimarchi956a4352008-12-10 15:52:06 +0100949static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000950{
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +0200951 int retries = 10;
wdenkde887eb2003-09-10 18:20:28 +0000952
wdenkaffae2b2002-08-17 09:36:01 +0000953 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100954 memset(&srb->cmd[0], 0, 12);
955 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200956 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100957 srb->datalen = 0;
958 srb->cmdlen = 12;
959 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000960 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100961 usb_request_sense(srb, ss);
962 wait_ms(100);
963 } while (retries--);
wdenkde887eb2003-09-10 18:20:28 +0000964
wdenkaffae2b2002-08-17 09:36:01 +0000965 return -1;
966}
967
Michael Trimarchi956a4352008-12-10 15:52:06 +0100968static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000969{
970 int retry;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100971 /* XXX retries */
972 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000973 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +0100974 memset(&srb->cmd[0], 0, 12);
975 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200976 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100977 srb->datalen = 8;
978 srb->cmdlen = 12;
979 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000980 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100981 } while (retry--);
wdenkde887eb2003-09-10 18:20:28 +0000982
wdenkaffae2b2002-08-17 09:36:01 +0000983 return -1;
984}
985
Michael Trimarchi956a4352008-12-10 15:52:06 +0100986static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
987 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000988{
Michael Trimarchi956a4352008-12-10 15:52:06 +0100989 memset(&srb->cmd[0], 0, 12);
990 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès134396c2010-10-05 22:04:26 +0200991 srb->cmd[1] = srb->lun << 5;
Michael Trimarchi956a4352008-12-10 15:52:06 +0100992 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
993 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
994 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
995 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
996 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
997 srb->cmd[8] = (unsigned char) blocks & 0xff;
998 srb->cmdlen = 12;
999 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
1000 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001001}
1002
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301003static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1004 unsigned short blocks)
1005{
1006 memset(&srb->cmd[0], 0, 12);
1007 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès134396c2010-10-05 22:04:26 +02001008 srb->cmd[1] = srb->lun << 5;
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301009 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1010 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1011 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1012 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1013 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1014 srb->cmd[8] = (unsigned char) blocks & 0xff;
1015 srb->cmdlen = 12;
1016 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1017 return ss->transport(srb, ss);
1018}
1019
wdenkaffae2b2002-08-17 09:36:01 +00001020
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001021#ifdef CONFIG_USB_BIN_FIXUP
1022/*
1023 * Some USB storage devices queried for SCSI identification data respond with
1024 * binary strings, which if output to the console freeze the terminal. The
1025 * workaround is to modify the vendor and product strings read from such
1026 * device with proper values (as reported by 'usb info').
1027 *
1028 * Vendor and product length limits are taken from the definition of
1029 * block_dev_desc_t in include/part.h.
1030 */
1031static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1032 unsigned char vendor[],
1033 unsigned char product[]) {
1034 const unsigned char max_vendor_len = 40;
1035 const unsigned char max_product_len = 20;
1036 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001037 strncpy((char *)vendor, "SMSC", max_vendor_len);
1038 strncpy((char *)product, "Flash Media Cntrller",
1039 max_product_len);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001040 }
1041}
1042#endif /* CONFIG_USB_BIN_FIXUP */
1043
wdenkaffae2b2002-08-17 09:36:01 +00001044#define USB_MAX_READ_BLK 20
1045
Michael Trimarchi956a4352008-12-10 15:52:06 +01001046unsigned long usb_stor_read(int device, unsigned long blknr,
1047 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001048{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001049 unsigned long start, blks, buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001050 unsigned short smallblks;
1051 struct usb_device *dev;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001052 int retry, i;
wdenk0e2874cb2004-03-02 14:05:39 +00001053 ccb *srb = &usb_ccb;
1054
1055 if (blkcnt == 0)
1056 return 0;
1057
1058 device &= 0xff;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001059 /* Setup device */
1060 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1061 dev = NULL;
1062 for (i = 0; i < USB_MAX_DEVICE; i++) {
1063 dev = usb_get_dev_index(i);
1064 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001065 return 0;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001066 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001067 break;
1068 }
1069
1070 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001071 srb->lun = usb_dev_desc[device].lun;
1072 buf_addr = (unsigned long)buffer;
1073 start = blknr;
1074 blks = blkcnt;
1075 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1076 printf("Device NOT ready\n Request Sense returned %02X %02X"
1077 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1078 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001079 return 0;
1080 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001081
1082 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1083 " buffer %lx\n", device, start, blks, buf_addr);
1084
wdenkaffae2b2002-08-17 09:36:01 +00001085 do {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001086 /* XXX need some comment here */
1087 retry = 2;
1088 srb->pdata = (unsigned char *)buf_addr;
1089 if (blks > USB_MAX_READ_BLK)
1090 smallblks = USB_MAX_READ_BLK;
1091 else
1092 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001093retry_it:
Michael Trimarchi956a4352008-12-10 15:52:06 +01001094 if (smallblks == USB_MAX_READ_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001095 usb_show_progress();
Michael Trimarchi956a4352008-12-10 15:52:06 +01001096 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1097 srb->pdata = (unsigned char *)buf_addr;
1098 if (usb_read_10(srb, (struct us_data *)dev->privptr, start,
1099 smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001100 USB_STOR_PRINTF("Read ERROR\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001101 usb_request_sense(srb, (struct us_data *)dev->privptr);
1102 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001103 goto retry_it;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001104 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001105 break;
1106 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001107 start += smallblks;
1108 blks -= smallblks;
1109 buf_addr += srb->datalen;
1110 } while (blks != 0);
1111
1112 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1113 start, smallblks, buf_addr);
1114
wdenkaffae2b2002-08-17 09:36:01 +00001115 usb_disable_asynch(0); /* asynch transfer allowed */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001116 if (blkcnt >= USB_MAX_READ_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001117 debug("\n");
Michael Trimarchi956a4352008-12-10 15:52:06 +01001118 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001119}
1120
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301121#define USB_MAX_WRITE_BLK 20
1122
1123unsigned long usb_stor_write(int device, unsigned long blknr,
1124 unsigned long blkcnt, const void *buffer)
1125{
1126 unsigned long start, blks, buf_addr;
1127 unsigned short smallblks;
1128 struct usb_device *dev;
1129 int retry, i;
1130 ccb *srb = &usb_ccb;
1131
1132 if (blkcnt == 0)
1133 return 0;
1134
1135 device &= 0xff;
1136 /* Setup device */
1137 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1138 dev = NULL;
1139 for (i = 0; i < USB_MAX_DEVICE; i++) {
1140 dev = usb_get_dev_index(i);
1141 if (dev == NULL)
1142 return 0;
1143 if (dev->devnum == usb_dev_desc[device].target)
1144 break;
1145 }
1146
1147 usb_disable_asynch(1); /* asynch transfer not allowed */
1148
1149 srb->lun = usb_dev_desc[device].lun;
1150 buf_addr = (unsigned long)buffer;
1151 start = blknr;
1152 blks = blkcnt;
1153 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1154 printf("Device NOT ready\n Request Sense returned %02X %02X"
1155 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1156 srb->sense_buf[13]);
1157 return 0;
1158 }
1159
1160 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1161 " buffer %lx\n", device, start, blks, buf_addr);
1162
1163 do {
1164 /* If write fails retry for max retry count else
1165 * return with number of blocks written successfully.
1166 */
1167 retry = 2;
1168 srb->pdata = (unsigned char *)buf_addr;
1169 if (blks > USB_MAX_WRITE_BLK)
1170 smallblks = USB_MAX_WRITE_BLK;
1171 else
1172 smallblks = (unsigned short) blks;
1173retry_it:
1174 if (smallblks == USB_MAX_WRITE_BLK)
1175 usb_show_progress();
1176 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1177 srb->pdata = (unsigned char *)buf_addr;
1178 if (usb_write_10(srb, (struct us_data *)dev->privptr, start,
1179 smallblks)) {
1180 USB_STOR_PRINTF("Write ERROR\n");
1181 usb_request_sense(srb, (struct us_data *)dev->privptr);
1182 if (retry--)
1183 goto retry_it;
1184 blkcnt -= blks;
1185 break;
1186 }
1187 start += smallblks;
1188 blks -= smallblks;
1189 buf_addr += srb->datalen;
1190 } while (blks != 0);
1191
1192 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1193 start, smallblks, buf_addr);
1194
1195 usb_disable_asynch(0); /* asynch transfer allowed */
1196 if (blkcnt >= USB_MAX_WRITE_BLK)
Wolfgang Denk660e9a42010-07-19 11:36:59 +02001197 debug("\n");
Mahavir Jaind43a0b82009-11-03 12:22:10 +05301198 return blkcnt;
1199
1200}
wdenkaffae2b2002-08-17 09:36:01 +00001201
1202/* Probe to see if a new device is actually a Storage device */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001203int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1204 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001205{
Tom Rix83b9e1d2009-10-31 12:37:38 -05001206 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001207 int i;
1208 unsigned int flags = 0;
1209
1210 int protocol = 0;
1211 int subclass = 0;
1212
wdenkaffae2b2002-08-17 09:36:01 +00001213 /* let's examine the device now */
1214 iface = &dev->config.if_desc[ifnum];
1215
1216#if 0
1217 /* this is the place to patch some storage devices */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001218 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1219 dev->descriptor.idProduct);
1220
1221 if ((dev->descriptor.idVendor) == 0x066b &&
1222 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001223 USB_STOR_PRINTF("patched for E-USB\n");
1224 protocol = US_PR_CB;
1225 subclass = US_SC_UFI; /* an assumption */
1226 }
1227#endif
1228
1229 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix83b9e1d2009-10-31 12:37:38 -05001230 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1231 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1232 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001233 /* if it's not a mass storage, we go no further */
1234 return 0;
1235 }
1236
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001237 memset(ss, 0, sizeof(struct us_data));
1238
wdenkaffae2b2002-08-17 09:36:01 +00001239 /* At this point, we know we've got a live one */
1240 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1241
1242 /* Initialize the us_data structure with some useful info */
1243 ss->flags = flags;
1244 ss->ifnum = ifnum;
1245 ss->pusb_dev = dev;
1246 ss->attention_done = 0;
1247
1248 /* If the device has subclass and protocol, then use that. Otherwise,
1249 * take data from the specific interface.
1250 */
1251 if (subclass) {
1252 ss->subclass = subclass;
1253 ss->protocol = protocol;
1254 } else {
Tom Rix83b9e1d2009-10-31 12:37:38 -05001255 ss->subclass = iface->desc.bInterfaceSubClass;
1256 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001257 }
1258
1259 /* set the handler pointers based on the protocol */
1260 USB_STOR_PRINTF("Transport: ");
1261 switch (ss->protocol) {
1262 case US_PR_CB:
1263 USB_STOR_PRINTF("Control/Bulk\n");
1264 ss->transport = usb_stor_CB_transport;
1265 ss->transport_reset = usb_stor_CB_reset;
1266 break;
1267
1268 case US_PR_CBI:
1269 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1270 ss->transport = usb_stor_CB_transport;
1271 ss->transport_reset = usb_stor_CB_reset;
1272 break;
wdenkde887eb2003-09-10 18:20:28 +00001273 case US_PR_BULK:
1274 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1275 ss->transport = usb_stor_BBB_transport;
1276 ss->transport_reset = usb_stor_BBB_reset;
1277 break;
wdenkaffae2b2002-08-17 09:36:01 +00001278 default:
wdenk5f495752004-02-26 23:46:20 +00001279 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001280 return 0;
1281 break;
1282 }
1283
1284 /*
1285 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1286 * An optional interrupt is OK (necessary for CBI protocol).
1287 * We will ignore any others.
1288 */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001289 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001290 /* is it an BULK endpoint? */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001291 if ((iface->ep_desc[i].bmAttributes &
1292 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001293 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1294 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1295 USB_ENDPOINT_NUMBER_MASK;
1296 else
Michael Trimarchi956a4352008-12-10 15:52:06 +01001297 ss->ep_out =
1298 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001299 USB_ENDPOINT_NUMBER_MASK;
1300 }
1301
1302 /* is it an interrupt endpoint? */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001303 if ((iface->ep_desc[i].bmAttributes &
1304 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001305 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1306 USB_ENDPOINT_NUMBER_MASK;
1307 ss->irqinterval = iface->ep_desc[i].bInterval;
1308 }
1309 }
1310 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1311 ss->ep_in, ss->ep_out, ss->ep_int);
1312
1313 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix83b9e1d2009-10-31 12:37:38 -05001314 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001315 !ss->ep_in || !ss->ep_out ||
1316 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1317 USB_STOR_PRINTF("Problems with device\n");
1318 return 0;
1319 }
1320 /* set class specific stuff */
wdenkde887eb2003-09-10 18:20:28 +00001321 /* We only handle certain protocols. Currently, these are
1322 * the only ones.
wdenk5f495752004-02-26 23:46:20 +00001323 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001324 */
wdenk5f495752004-02-26 23:46:20 +00001325 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1326 ss->subclass != US_SC_8070) {
Michael Trimarchi956a4352008-12-10 15:52:06 +01001327 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001328 return 0;
1329 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001330 if (ss->ep_int) {
1331 /* we had found an interrupt endpoint, prepare irq pipe
1332 * set up the IRQ pipe and handler
1333 */
wdenkaffae2b2002-08-17 09:36:01 +00001334 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1335 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1336 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchi956a4352008-12-10 15:52:06 +01001337 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001338 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001339 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001340 return 1;
1341}
1342
Michael Trimarchi956a4352008-12-10 15:52:06 +01001343int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1344 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001345{
Michael Trimarchi956a4352008-12-10 15:52:06 +01001346 unsigned char perq, modi;
wdenkaffae2b2002-08-17 09:36:01 +00001347 unsigned long cap[2];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001348 unsigned long *capacity, *blksz;
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001349 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001350
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001351 pccb->pdata = usb_stor_buf;
1352
1353 dev_desc->target = dev->devnum;
1354 pccb->lun = dev_desc->lun;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001355 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001356
Michael Trimarchi956a4352008-12-10 15:52:06 +01001357 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001358 return -1;
Wolfgang Denkd06ce5d2005-08-02 17:06:17 +02001359
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001360 perq = usb_stor_buf[0];
1361 modi = usb_stor_buf[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001362
1363 if ((perq & 0x1f) == 0x1f) {
1364 /* skip unknown devices */
1365 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001366 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001367 if ((modi&0x80) == 0x80) {
1368 /* drive is removable */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001369 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001370 }
1371 memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
1372 memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
1373 memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001374 dev_desc->vendor[8] = 0;
1375 dev_desc->product[16] = 0;
1376 dev_desc->revision[4] = 0;
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001377#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchi956a4352008-12-10 15:52:06 +01001378 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1379 (uchar *)dev_desc->product);
Bartlomiej Sieka9d47ad42006-08-22 10:38:18 +02001380#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchi956a4352008-12-10 15:52:06 +01001381 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1382 usb_stor_buf[3]);
1383 if (usb_test_unit_ready(pccb, ss)) {
1384 printf("Device NOT ready\n"
1385 " Request Sense returned %02X %02X %02X\n",
1386 pccb->sense_buf[2], pccb->sense_buf[12],
1387 pccb->sense_buf[13]);
1388 if (dev_desc->removable == 1) {
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001389 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001390 return 1;
1391 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001392 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001393 }
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001394 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001395 memset(pccb->pdata, 0, 8);
1396 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001397 printf("READ_CAP ERROR\n");
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001398 cap[0] = 2880;
1399 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001400 }
Michael Trimarchi956a4352008-12-10 15:52:06 +01001401 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1402 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001403#if 0
Michael Trimarchi956a4352008-12-10 15:52:06 +01001404 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1405 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001406#endif
Christian Eggers4e0e8d02008-05-21 22:12:00 +02001407 cap[0] = cpu_to_be32(cap[0]);
1408 cap[1] = cpu_to_be32(cap[1]);
1409
wdenkde887eb2003-09-10 18:20:28 +00001410 /* this assumes bigendian! */
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001411 cap[0] += 1;
1412 capacity = &cap[0];
1413 blksz = &cap[1];
Michael Trimarchi956a4352008-12-10 15:52:06 +01001414 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1415 *capacity, *blksz);
Wolfgang Denkc7a4f7d2005-07-21 11:57:57 +02001416 dev_desc->lba = *capacity;
1417 dev_desc->blksz = *blksz;
1418 dev_desc->type = perq;
Michael Trimarchi956a4352008-12-10 15:52:06 +01001419 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1420 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001421
1422 init_part(dev_desc);
1423
Michael Trimarchi956a4352008-12-10 15:52:06 +01001424 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001425 return 1;
1426}