blob: de84c8d7d0185ddb2a5ab986a74f936473ec3428 [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
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
wdenk149dded2003-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;
wdenk80885a92004-02-26 23:46:20 +0000111#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100112static __u32 CBWTag;
wdenk149dded2003-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
wdenk80885a92004-02-26 23:46:20 +0000122# define CSWSTATUS_FAILED 0x1
wdenk149dded2003-09-10 18:20:28 +0000123# define CSWSTATUS_PHASE 0x2
124} umass_bbb_csw_t;
wdenk80885a92004-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-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 */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +0000154 unsigned long max_xfer_blk; /* Max blocks per xfer */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100155 ccb *srb; /* current srb */
156 trans_reset transport_reset; /* reset routine */
157 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000158};
159
160static struct us_data usb_stor[USB_MAX_STOR_DEV];
161
162
wdenk80885a92004-02-26 23:46:20 +0000163#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000164#define USB_STOR_TRANSPORT_FAILED -1
165#define USB_STOR_TRANSPORT_ERROR -2
166
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100167int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
168 block_dev_desc_t *dev_desc);
169int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
170 struct us_data *ss);
171unsigned long usb_stor_read(int device, unsigned long blknr,
172 unsigned long blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530173unsigned long usb_stor_write(int device, unsigned long blknr,
174 unsigned long blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000175struct usb_device * usb_get_dev_index(int index);
176void uhci_show_temp_int_td(void);
177
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000178#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000179block_dev_desc_t *usb_stor_get_dev(int index)
180{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200181 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000182}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000183#endif
wdenkaffae2b2002-08-17 09:36:01 +0000184
185void usb_show_progress(void)
186{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200187 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000188}
189
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100190/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200191 * show info on storage devices; 'usb start/init' must be invoked earlier
192 * as we only retrieve structures populated during devices initialization
193 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100194int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200195{
196 int i;
197
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100198 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200199 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100200 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200201 dev_print(&usb_dev_desc[i]);
202 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100203 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100204 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700205
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100206 printf("No storage devices, perhaps not 'usb start'ed..?\n");
207 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200208}
209
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200210static unsigned int usb_get_max_lun(struct us_data *us)
211{
212 int len;
213 unsigned char result;
214 len = usb_control_msg(us->pusb_dev,
215 usb_rcvctrlpipe(us->pusb_dev, 0),
216 US_BBB_GET_MAX_LUN,
217 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
218 0, us->ifnum,
219 &result, sizeof(result),
220 USB_CNTL_TIMEOUT * 5);
221 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
222 len, (int) result);
223 return (len > 0) ? result : 0;
224}
225
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100226/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200227 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000228 * to the user if mode = 1
229 * returns current device or -1 if no
230 */
231int usb_stor_scan(int mode)
232{
233 unsigned char i;
234 struct usb_device *dev;
235
wdenk149dded2003-09-10 18:20:28 +0000236 /* GJ */
237 memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
238
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100239 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200240 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100241
wdenkaffae2b2002-08-17 09:36:01 +0000242 usb_disable_asynch(1); /* asynch transfer not allowed */
243
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
245 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100246 usb_dev_desc[i].if_type = IF_TYPE_USB;
247 usb_dev_desc[i].dev = i;
248 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200249 usb_dev_desc[i].target = 0xff;
250 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100251 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530252 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000253 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200254
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100255 usb_max_devs = 0;
256 for (i = 0; i < USB_MAX_DEVICE; i++) {
257 dev = usb_get_dev_index(i); /* get device */
258 USB_STOR_PRINTF("i=%d\n", i);
259 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100260 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100261
262 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200263 /* OK, it's a storage device. Iterate over its LUNs
264 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100265 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200266 int lun, max_lun, start = usb_max_devs;
267
268 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
269 for (lun = 0;
270 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
271 lun++) {
272 usb_dev_desc[usb_max_devs].lun = lun;
273 if (usb_stor_get_info(dev, &usb_stor[start],
274 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000275 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100276 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200277 }
278 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100279 /* if storage device */
280 if (usb_max_devs == USB_MAX_STOR_DEV) {
281 printf("max USB Storage Device reached: %d stopping\n",
282 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000283 break;
284 }
285 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200286
wdenkaffae2b2002-08-17 09:36:01 +0000287 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200288 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100289 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000290 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100291 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000292}
293
294static int usb_stor_irq(struct usb_device *dev)
295{
296 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100297 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000298
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100299 if (us->ip_wanted)
300 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000301 return 0;
302}
303
304
305#ifdef USB_STOR_DEBUG
306
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100307static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000308{
309 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100310 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
311 for (i = 0; i < 12; i++)
312 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000313 printf("\n");
314}
315
316static void display_int_status(unsigned long tmp)
317{
318 printf("Status: %s %s %s %s %s %s %s\n",
319 (tmp & USB_ST_ACTIVE) ? "Active" : "",
320 (tmp & USB_ST_STALLED) ? "Stalled" : "",
321 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
322 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
323 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
324 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
325 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
326}
327#endif
328/***********************************************************************
329 * Data transfer routines
330 ***********************************************************************/
331
332static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
333{
334 int max_size;
335 int this_xfer;
336 int result;
337 int partial;
338 int maxtry;
339 int stat;
340
341 /* determine the maximum packet size for these transfers */
342 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
343
344 /* while we have data left to transfer */
345 while (length) {
346
347 /* calculate how long this will be -- maximum or a remainder */
348 this_xfer = length > max_size ? max_size : length;
349 length -= this_xfer;
350
351 /* setup the retry counter */
352 maxtry = 10;
353
354 /* set up the transfer loop */
355 do {
356 /* transfer the data */
357 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
358 (unsigned int)buf, this_xfer, 11 - maxtry);
359 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100360 this_xfer, &partial,
361 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000362 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
363 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100364 if (us->pusb_dev->status != 0) {
365 /* if we stall, we need to clear it before
366 * we go on
367 */
wdenkaffae2b2002-08-17 09:36:01 +0000368#ifdef USB_STOR_DEBUG
369 display_int_status(us->pusb_dev->status);
370#endif
371 if (us->pusb_dev->status & USB_ST_STALLED) {
372 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
373 stat = us->pusb_dev->status;
374 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100375 us->pusb_dev->status = stat;
376 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200377 USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000378 return 0;
379 }
380 else
381 return result;
382 }
383 if (us->pusb_dev->status & USB_ST_NAK_REC) {
384 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
385 return result;
386 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100387 USB_STOR_PRINTF("bulk transferred with error");
388 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200389 USB_STOR_PRINTF(" %ld, but data ok\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100390 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000391 return 0;
392 }
393 /* if our try counter reaches 0, bail out */
Marek Vasut4b210e82011-10-25 11:39:17 +0200394 USB_STOR_PRINTF(" %ld, data %d\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100395 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000396 if (!maxtry--)
397 return result;
398 }
399 /* update to show what data was transferred */
400 this_xfer -= partial;
401 buf += partial;
402 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100403 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000404 }
405
406 /* if we get here, we're done and successful */
407 return 0;
408}
409
wdenk149dded2003-09-10 18:20:28 +0000410static int usb_stor_BBB_reset(struct us_data *us)
411{
412 int result;
413 unsigned int pipe;
414
415 /*
416 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
417 *
418 * For Reset Recovery the host shall issue in the following order:
419 * a) a Bulk-Only Mass Storage Reset
420 * b) a Clear Feature HALT to the Bulk-In endpoint
421 * c) a Clear Feature HALT to the Bulk-Out endpoint
422 *
423 * This is done in 3 steps.
424 *
425 * If the reset doesn't succeed, the device should be port reset.
426 *
427 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
428 */
429 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100430 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
431 US_BBB_RESET,
432 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
433 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200434
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100435 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000436 USB_STOR_PRINTF("RESET:stall\n");
437 return -1;
438 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200439
wdenk149dded2003-09-10 18:20:28 +0000440 /* long wait for reset */
441 wait_ms(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200442 USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100443 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000444 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
445 result = usb_clear_halt(us->pusb_dev, pipe);
446 /* long wait for reset */
447 wait_ms(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200448 USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100449 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000450 /* long wait for reset */
451 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
452 result = usb_clear_halt(us->pusb_dev, pipe);
453 wait_ms(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200454 USB_STOR_PRINTF("BBB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100455 " clearing OUT endpoint\n", result,
456 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000457 USB_STOR_PRINTF("BBB_reset done\n");
458 return 0;
459}
460
wdenkaffae2b2002-08-17 09:36:01 +0000461/* FIXME: this reset function doesn't really reset the port, and it
462 * should. Actually it should probably do what it's doing here, and
463 * reset the port physically
464 */
465static int usb_stor_CB_reset(struct us_data *us)
466{
467 unsigned char cmd[12];
468 int result;
469
470 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100471 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000472 cmd[0] = SCSI_SEND_DIAG;
473 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100474 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
475 US_CBI_ADSC,
476 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
477 0, us->ifnum, cmd, sizeof(cmd),
478 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000479
480 /* long wait for reset */
481 wait_ms(1500);
Marek Vasut4b210e82011-10-25 11:39:17 +0200482 USB_STOR_PRINTF("CB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100483 " clearing endpoint halt\n", result,
484 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000485 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
486 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
487
488 USB_STOR_PRINTF("CB_reset done\n");
489 return 0;
490}
491
wdenk149dded2003-09-10 18:20:28 +0000492/*
493 * Set up the command for a BBB device. Note that the actual SCSI
494 * command is copied into cbw.CBWCDB.
495 */
496int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
497{
498 int result;
499 int actlen;
500 int dir_in;
501 unsigned int pipe;
502 umass_bbb_cbw_t cbw;
503
504 dir_in = US_DIRECTION(srb->cmd[0]);
505
506#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100507 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
508 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
509 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000510 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100511 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000512 printf("cmd[%d] %#x ", result, srb->cmd[result]);
513 printf("\n");
514 }
515#endif
516 /* sanity checks */
517 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
518 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
519 return -1;
520 }
521
522 /* always OUT to the ep */
523 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
524
Christian Eggersc9182612008-05-21 22:12:00 +0200525 cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
526 cbw.dCBWTag = cpu_to_le32(CBWTag++);
527 cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100528 cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
wdenk149dded2003-09-10 18:20:28 +0000529 cbw.bCBWLUN = srb->lun;
530 cbw.bCDBLength = srb->cmdlen;
531 /* copy the command data into the CBW command data buffer */
532 /* DST SRC LEN!!! */
533 memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100534 result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
535 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000536 if (result < 0)
537 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
538 return result;
539}
540
wdenkaffae2b2002-08-17 09:36:01 +0000541/* FIXME: we also need a CBI_command which sets up the completion
542 * interrupt, and waits for it
543 */
544int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
545{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200546 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000548 unsigned int pipe;
549 unsigned long status;
550
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100551 retry = 5;
552 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000553
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100554 if (dir_in)
555 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
556 else
557 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
558
559 while (retry--) {
560 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000561#ifdef USB_STOR_DEBUG
562 usb_show_srb(srb);
563#endif
564 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100565 result = usb_control_msg(us->pusb_dev,
566 usb_sndctrlpipe(us->pusb_dev , 0),
567 US_CBI_ADSC,
568 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000569 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100570 srb->cmd, srb->cmdlen,
571 USB_CNTL_TIMEOUT * 5);
572 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
Marek Vasut4b210e82011-10-25 11:39:17 +0200573 " status %lX\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000574 /* check the return code for the command */
575 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100576 if (us->pusb_dev->status & USB_ST_STALLED) {
577 status = us->pusb_dev->status;
578 USB_STOR_PRINTF(" stall during command found,"
579 " clear pipe\n");
580 usb_clear_halt(us->pusb_dev,
581 usb_sndctrlpipe(us->pusb_dev, 0));
582 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000583 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100584 USB_STOR_PRINTF(" error during command %02X"
Marek Vasut4b210e82011-10-25 11:39:17 +0200585 " Stat = %lX\n", srb->cmd[0],
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100586 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000587 return result;
588 }
589 /* transfer the data payload for this command, if one exists*/
590
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100591 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
592 " direction is %s to go 0x%lx\n", result,
593 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000594 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100595 result = us_one_transfer(us, pipe, (char *)srb->pdata,
596 srb->datalen);
597 USB_STOR_PRINTF("CBI attempted to transfer data,"
598 " result is %d status %lX, len %d\n",
599 result, us->pusb_dev->status,
600 us->pusb_dev->act_len);
601 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000602 break;
603 } /* if (srb->datalen) */
604 else
605 break;
606 }
607 /* return result */
608
609 return result;
610}
611
612
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100613int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000614{
615 int timeout;
616
wdenk80885a92004-02-26 23:46:20 +0000617 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100618 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000619 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
620 timeout = 1000;
621 while (timeout--) {
622 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000623 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100624 wait_ms(10);
wdenkaffae2b2002-08-17 09:36:01 +0000625 }
626 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100627 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000628 us->ip_wanted = 0;
629 return USB_STOR_TRANSPORT_ERROR;
630 }
wdenk80885a92004-02-26 23:46:20 +0000631 USB_STOR_PRINTF
632 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
633 us->ip_data, us->pusb_dev->irq_act_len,
634 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000635 /* UFI gives us ASC and ASCQ, like a request sense */
636 if (us->subclass == US_SC_UFI) {
637 if (srb->cmd[0] == SCSI_REQ_SENSE ||
638 srb->cmd[0] == SCSI_INQUIRY)
639 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000640 else if (us->ip_data)
641 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000642 else
wdenk80885a92004-02-26 23:46:20 +0000643 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000644 }
645 /* otherwise, we interpret the data normally */
646 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000647 case 0x0001:
648 return USB_STOR_TRANSPORT_GOOD;
649 case 0x0002:
650 return USB_STOR_TRANSPORT_FAILED;
651 default:
652 return USB_STOR_TRANSPORT_ERROR;
653 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000654 return USB_STOR_TRANSPORT_ERROR;
655}
656
657#define USB_TRANSPORT_UNKNOWN_RETRY 5
658#define USB_TRANSPORT_NOT_READY_RETRY 10
659
wdenk149dded2003-09-10 18:20:28 +0000660/* clear a stall on an endpoint - special for BBB devices */
661int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
662{
663 int result;
664
665 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100666 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000667 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100668 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000669 return result;
670}
671
672int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
673{
674 int result, retry;
675 int dir_in;
676 int actlen, data_actlen;
677 unsigned int pipe, pipein, pipeout;
678 umass_bbb_csw_t csw;
679#ifdef BBB_XPORT_TRACE
680 unsigned char *ptr;
681 int index;
682#endif
683
684 dir_in = US_DIRECTION(srb->cmd[0]);
685
686 /* COMMAND phase */
687 USB_STOR_PRINTF("COMMAND phase\n");
688 result = usb_stor_BBB_comdat(srb, us);
689 if (result < 0) {
690 USB_STOR_PRINTF("failed to send CBW status %ld\n",
691 us->pusb_dev->status);
692 usb_stor_BBB_reset(us);
693 return USB_STOR_TRANSPORT_FAILED;
694 }
695 wait_ms(5);
696 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
697 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
698 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000699 data_actlen = 0;
700 /* no data, go immediately to the STATUS phase */
701 if (srb->datalen == 0)
702 goto st;
wdenk80885a92004-02-26 23:46:20 +0000703 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000704 if (dir_in)
705 pipe = pipein;
706 else
707 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100708 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
709 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000710 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100711 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000712 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000713 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100714 result = usb_stor_BBB_clear_endpt_stall(us,
715 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000716 if (result >= 0)
717 /* continue on to STATUS phase */
718 goto st;
719 }
720 if (result < 0) {
721 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
722 us->pusb_dev->status);
723 usb_stor_BBB_reset(us);
724 return USB_STOR_TRANSPORT_FAILED;
725 }
726#ifdef BBB_XPORT_TRACE
727 for (index = 0; index < data_actlen; index++)
728 printf("pdata[%d] %#x ", index, srb->pdata[index]);
729 printf("\n");
730#endif
731 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100732st:
wdenk149dded2003-09-10 18:20:28 +0000733 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100734again:
wdenk149dded2003-09-10 18:20:28 +0000735 USB_STOR_PRINTF("STATUS phase\n");
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200736 result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200737 &actlen, USB_CNTL_TIMEOUT*5);
738
wdenk149dded2003-09-10 18:20:28 +0000739 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100740 if ((result < 0) && (retry < 1) &&
741 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000742 USB_STOR_PRINTF("STATUS:stall\n");
743 /* clear the STALL on the endpoint */
744 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
745 if (result >= 0 && (retry++ < 1))
746 /* do a retry */
747 goto again;
748 }
749 if (result < 0) {
750 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
751 us->pusb_dev->status);
752 usb_stor_BBB_reset(us);
753 return USB_STOR_TRANSPORT_FAILED;
754 }
755#ifdef BBB_XPORT_TRACE
756 ptr = (unsigned char *)&csw;
757 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
758 printf("ptr[%d] %#x ", index, ptr[index]);
759 printf("\n");
760#endif
761 /* misuse pipe to get the residue */
Christian Eggersc9182612008-05-21 22:12:00 +0200762 pipe = le32_to_cpu(csw.dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000763 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
764 pipe = srb->datalen - data_actlen;
Christian Eggersc9182612008-05-21 22:12:00 +0200765 if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000766 USB_STOR_PRINTF("!CSWSIGNATURE\n");
767 usb_stor_BBB_reset(us);
768 return USB_STOR_TRANSPORT_FAILED;
Christian Eggersc9182612008-05-21 22:12:00 +0200769 } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000770 USB_STOR_PRINTF("!Tag\n");
771 usb_stor_BBB_reset(us);
772 return USB_STOR_TRANSPORT_FAILED;
773 } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
774 USB_STOR_PRINTF(">PHASE\n");
775 usb_stor_BBB_reset(us);
776 return USB_STOR_TRANSPORT_FAILED;
777 } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
778 USB_STOR_PRINTF("=PHASE\n");
779 usb_stor_BBB_reset(us);
780 return USB_STOR_TRANSPORT_FAILED;
781 } else if (data_actlen > srb->datalen) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200782 USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
wdenk149dded2003-09-10 18:20:28 +0000783 data_actlen, srb->datalen);
784 return USB_STOR_TRANSPORT_FAILED;
785 } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
786 USB_STOR_PRINTF("FAILED\n");
787 return USB_STOR_TRANSPORT_FAILED;
788 }
789
790 return result;
791}
792
wdenkaffae2b2002-08-17 09:36:01 +0000793int usb_stor_CB_transport(ccb *srb, struct us_data *us)
794{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100795 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000796 ccb *psrb;
797 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100798 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000799
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200800 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100801 status = USB_STOR_TRANSPORT_GOOD;
802 retry = 0;
803 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000804 /* issue the command */
805do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 result = usb_stor_CB_comdat(srb, us);
Marek Vasut4b210e82011-10-25 11:39:17 +0200807 USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100808 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000809 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100810 if (us->protocol == US_PR_CBI) {
811 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000812 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100813 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000814 USB_STOR_PRINTF(" USB CBI Command Error\n");
815 return status;
816 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100817 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
818 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
819 if (!us->ip_data) {
820 /* if the status is good, report it */
821 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000822 USB_STOR_PRINTF(" USB CBI Command Good\n");
823 return status;
824 }
825 }
826 }
827 /* do we have to issue an auto request? */
828 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100829 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200830 USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000831 us->transport_reset(us);
832 return USB_STOR_TRANSPORT_ERROR;
833 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100834 if ((us->protocol == US_PR_CBI) &&
835 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
836 (srb->cmd[0] == SCSI_INQUIRY))) {
837 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000838 USB_STOR_PRINTF("No auto request and good\n");
839 return USB_STOR_TRANSPORT_GOOD;
840 }
841 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100842 memset(&psrb->cmd[0], 0, 12);
843 psrb->cmd[0] = SCSI_REQ_SENSE;
844 psrb->cmd[1] = srb->lun << 5;
845 psrb->cmd[4] = 18;
846 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200847 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000849 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 result = usb_stor_CB_comdat(psrb, us);
851 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000852 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 if (us->protocol == US_PR_CBI)
854 status = usb_stor_CBI_get_status(psrb, us);
855
856 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200857 USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100858 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000859 return USB_STOR_TRANSPORT_ERROR;
860 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100861 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
862 srb->sense_buf[0], srb->sense_buf[2],
863 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000864 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100865 if ((srb->sense_buf[2] == 0) &&
866 (srb->sense_buf[12] == 0) &&
867 (srb->sense_buf[13] == 0)) {
868 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000869 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 }
871
wdenkaffae2b2002-08-17 09:36:01 +0000872 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100873 switch (srb->sense_buf[2]) {
874 case 0x01:
875 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000876 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000877 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878 case 0x02:
879 /* Not Ready */
880 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
881 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
882 " 0x%02X (NOT READY)\n", srb->cmd[0],
883 srb->sense_buf[0], srb->sense_buf[2],
884 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000885 return USB_STOR_TRANSPORT_FAILED;
886 } else {
887 wait_ms(100);
888 goto do_retry;
889 }
890 break;
891 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100892 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
893 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
894 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
895 srb->sense_buf[2], srb->sense_buf[12],
896 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000897 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100898 } else
wdenk149dded2003-09-10 18:20:28 +0000899 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000900 break;
wdenkaffae2b2002-08-17 09:36:01 +0000901 }
902 return USB_STOR_TRANSPORT_FAILED;
903}
904
905
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000907{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908 int retry, i;
909 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000910 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911 memset(&srb->cmd[0], 0, 12);
912 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200913 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 srb->cmd[4] = 36;
915 srb->datalen = 36;
916 srb->cmdlen = 12;
917 i = ss->transport(srb, ss);
918 USB_STOR_PRINTF("inquiry returns %d\n", i);
919 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000920 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200921 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000922
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000924 printf("error in inquiry\n");
925 return -1;
926 }
927 return 0;
928}
929
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100930static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000931{
932 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000933
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100934 ptr = (char *)srb->pdata;
935 memset(&srb->cmd[0], 0, 12);
936 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200937 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100938 srb->cmd[4] = 18;
939 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200940 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100941 srb->cmdlen = 12;
942 ss->transport(srb, ss);
943 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
944 srb->sense_buf[2], srb->sense_buf[12],
945 srb->sense_buf[13]);
946 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000947 return 0;
948}
949
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100950static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000951{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200952 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000953
wdenkaffae2b2002-08-17 09:36:01 +0000954 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955 memset(&srb->cmd[0], 0, 12);
956 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200957 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 srb->datalen = 0;
959 srb->cmdlen = 12;
960 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000961 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100962 usb_request_sense(srb, ss);
963 wait_ms(100);
964 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000965
wdenkaffae2b2002-08-17 09:36:01 +0000966 return -1;
967}
968
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100969static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000970{
971 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100972 /* XXX retries */
973 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000974 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100975 memset(&srb->cmd[0], 0, 12);
976 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200977 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100978 srb->datalen = 8;
979 srb->cmdlen = 12;
980 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000981 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100982 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000983
wdenkaffae2b2002-08-17 09:36:01 +0000984 return -1;
985}
986
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
988 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000989{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100990 memset(&srb->cmd[0], 0, 12);
991 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200992 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100993 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
994 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
995 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
996 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
997 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
998 srb->cmd[8] = (unsigned char) blocks & 0xff;
999 srb->cmdlen = 12;
1000 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
1001 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001002}
1003
Mahavir Jain127e1082009-11-03 12:22:10 +05301004static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1005 unsigned short blocks)
1006{
1007 memset(&srb->cmd[0], 0, 12);
1008 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001009 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301010 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1011 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1012 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1013 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1014 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1015 srb->cmd[8] = (unsigned char) blocks & 0xff;
1016 srb->cmdlen = 12;
1017 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1018 return ss->transport(srb, ss);
1019}
1020
wdenkaffae2b2002-08-17 09:36:01 +00001021
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001022#ifdef CONFIG_USB_BIN_FIXUP
1023/*
1024 * Some USB storage devices queried for SCSI identification data respond with
1025 * binary strings, which if output to the console freeze the terminal. The
1026 * workaround is to modify the vendor and product strings read from such
1027 * device with proper values (as reported by 'usb info').
1028 *
1029 * Vendor and product length limits are taken from the definition of
1030 * block_dev_desc_t in include/part.h.
1031 */
1032static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1033 unsigned char vendor[],
1034 unsigned char product[]) {
1035 const unsigned char max_vendor_len = 40;
1036 const unsigned char max_product_len = 20;
1037 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001038 strncpy((char *)vendor, "SMSC", max_vendor_len);
1039 strncpy((char *)product, "Flash Media Cntrller",
1040 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001041 }
1042}
1043#endif /* CONFIG_USB_BIN_FIXUP */
1044
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001045unsigned long usb_stor_read(int device, unsigned long blknr,
1046 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001047{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001048 unsigned long start, blks, buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001049 unsigned short smallblks;
1050 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001051 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001052 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001053 ccb *srb = &usb_ccb;
1054
1055 if (blkcnt == 0)
1056 return 0;
1057
1058 device &= 0xff;
Michael Trimarchia0cb3fc2008-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 Trimarchia0cb3fc2008-12-10 15:52:06 +01001066 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001067 break;
1068 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001069 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001070
1071 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001072 srb->lun = usb_dev_desc[device].lun;
1073 buf_addr = (unsigned long)buffer;
1074 start = blknr;
1075 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001076 if (usb_test_unit_ready(srb, ss)) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001077 printf("Device NOT ready\n Request Sense returned %02X %02X"
1078 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1079 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001080 return 0;
1081 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001082
1083 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1084 " buffer %lx\n", device, start, blks, buf_addr);
1085
wdenkaffae2b2002-08-17 09:36:01 +00001086 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001087 /* XXX need some comment here */
1088 retry = 2;
1089 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001090 if (blks > ss->max_xfer_blk)
1091 smallblks = ss->max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092 else
1093 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001094retry_it:
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001095 if (smallblks == ss->max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001096 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001097 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1098 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001099 if (usb_read_10(srb, ss, start, smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001100 USB_STOR_PRINTF("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001101 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001102 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001103 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001104 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001105 break;
1106 }
Michael Trimarchia0cb3fc2008-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 */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001116 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001117 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001118 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001119}
1120
Mahavir Jain127e1082009-11-03 12:22:10 +05301121unsigned long usb_stor_write(int device, unsigned long blknr,
1122 unsigned long blkcnt, const void *buffer)
1123{
1124 unsigned long start, blks, buf_addr;
1125 unsigned short smallblks;
1126 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001127 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301128 int retry, i;
1129 ccb *srb = &usb_ccb;
1130
1131 if (blkcnt == 0)
1132 return 0;
1133
1134 device &= 0xff;
1135 /* Setup device */
1136 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1137 dev = NULL;
1138 for (i = 0; i < USB_MAX_DEVICE; i++) {
1139 dev = usb_get_dev_index(i);
1140 if (dev == NULL)
1141 return 0;
1142 if (dev->devnum == usb_dev_desc[device].target)
1143 break;
1144 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001145 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301146
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;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001153 if (usb_test_unit_ready(srb, ss)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301154 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;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001169 if (blks > ss->max_xfer_blk)
1170 smallblks = ss->max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301171 else
1172 smallblks = (unsigned short) blks;
1173retry_it:
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001174 if (smallblks == ss->max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301175 usb_show_progress();
1176 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1177 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001178 if (usb_write_10(srb, ss, start, smallblks)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301179 USB_STOR_PRINTF("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001180 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301181 if (retry--)
1182 goto retry_it;
1183 blkcnt -= blks;
1184 break;
1185 }
1186 start += smallblks;
1187 blks -= smallblks;
1188 buf_addr += srb->datalen;
1189 } while (blks != 0);
1190
1191 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1192 start, smallblks, buf_addr);
1193
1194 usb_disable_asynch(0); /* asynch transfer allowed */
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001195 if (blkcnt >= ss->max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001196 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301197 return blkcnt;
1198
1199}
wdenkaffae2b2002-08-17 09:36:01 +00001200
1201/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001202int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1203 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001204{
Tom Rix8f8bd562009-10-31 12:37:38 -05001205 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001206 int i;
1207 unsigned int flags = 0;
1208
1209 int protocol = 0;
1210 int subclass = 0;
1211
wdenkaffae2b2002-08-17 09:36:01 +00001212 /* let's examine the device now */
1213 iface = &dev->config.if_desc[ifnum];
1214
1215#if 0
1216 /* this is the place to patch some storage devices */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001217 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1218 dev->descriptor.idProduct);
1219
1220 if ((dev->descriptor.idVendor) == 0x066b &&
1221 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001222 USB_STOR_PRINTF("patched for E-USB\n");
1223 protocol = US_PR_CB;
1224 subclass = US_SC_UFI; /* an assumption */
1225 }
1226#endif
1227
1228 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001229 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1230 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1231 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001232 /* if it's not a mass storage, we go no further */
1233 return 0;
1234 }
1235
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001236 memset(ss, 0, sizeof(struct us_data));
1237
wdenkaffae2b2002-08-17 09:36:01 +00001238 /* At this point, we know we've got a live one */
1239 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1240
1241 /* Initialize the us_data structure with some useful info */
1242 ss->flags = flags;
1243 ss->ifnum = ifnum;
1244 ss->pusb_dev = dev;
1245 ss->attention_done = 0;
1246
1247 /* If the device has subclass and protocol, then use that. Otherwise,
1248 * take data from the specific interface.
1249 */
1250 if (subclass) {
1251 ss->subclass = subclass;
1252 ss->protocol = protocol;
1253 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001254 ss->subclass = iface->desc.bInterfaceSubClass;
1255 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001256 }
1257
1258 /* set the handler pointers based on the protocol */
1259 USB_STOR_PRINTF("Transport: ");
1260 switch (ss->protocol) {
1261 case US_PR_CB:
1262 USB_STOR_PRINTF("Control/Bulk\n");
1263 ss->transport = usb_stor_CB_transport;
1264 ss->transport_reset = usb_stor_CB_reset;
1265 break;
1266
1267 case US_PR_CBI:
1268 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1269 ss->transport = usb_stor_CB_transport;
1270 ss->transport_reset = usb_stor_CB_reset;
1271 break;
wdenk149dded2003-09-10 18:20:28 +00001272 case US_PR_BULK:
1273 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1274 ss->transport = usb_stor_BBB_transport;
1275 ss->transport_reset = usb_stor_BBB_reset;
1276 break;
wdenkaffae2b2002-08-17 09:36:01 +00001277 default:
wdenk80885a92004-02-26 23:46:20 +00001278 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001279 return 0;
1280 break;
1281 }
1282
1283 /*
1284 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1285 * An optional interrupt is OK (necessary for CBI protocol).
1286 * We will ignore any others.
1287 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001288 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001289 /* is it an BULK endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001290 if ((iface->ep_desc[i].bmAttributes &
1291 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001292 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1293 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1294 USB_ENDPOINT_NUMBER_MASK;
1295 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001296 ss->ep_out =
1297 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001298 USB_ENDPOINT_NUMBER_MASK;
1299 }
1300
1301 /* is it an interrupt endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001302 if ((iface->ep_desc[i].bmAttributes &
1303 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001304 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1305 USB_ENDPOINT_NUMBER_MASK;
1306 ss->irqinterval = iface->ep_desc[i].bInterval;
1307 }
1308 }
1309 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1310 ss->ep_in, ss->ep_out, ss->ep_int);
1311
1312 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001313 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001314 !ss->ep_in || !ss->ep_out ||
1315 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1316 USB_STOR_PRINTF("Problems with device\n");
1317 return 0;
1318 }
1319 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001320 /* We only handle certain protocols. Currently, these are
1321 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001322 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001323 */
wdenk80885a92004-02-26 23:46:20 +00001324 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1325 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001326 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001327 return 0;
1328 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001329 if (ss->ep_int) {
1330 /* we had found an interrupt endpoint, prepare irq pipe
1331 * set up the IRQ pipe and handler
1332 */
wdenkaffae2b2002-08-17 09:36:01 +00001333 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1334 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1335 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001336 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001337 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001338 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001339 return 1;
1340}
1341
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001342int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1343 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001344{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001345 unsigned char perq, modi;
wdenkaffae2b2002-08-17 09:36:01 +00001346 unsigned long cap[2];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001347 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001348 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001349
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001350 pccb->pdata = usb_stor_buf;
1351
1352 dev_desc->target = dev->devnum;
1353 pccb->lun = dev_desc->lun;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001354 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001355
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001356 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001357 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001358
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001359 perq = usb_stor_buf[0];
1360 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001361
1362 if ((perq & 0x1f) == 0x1f) {
1363 /* skip unknown devices */
1364 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001365 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001366 if ((modi&0x80) == 0x80) {
1367 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001368 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001369 }
1370 memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
1371 memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
1372 memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001373 dev_desc->vendor[8] = 0;
1374 dev_desc->product[16] = 0;
1375 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001376#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001377 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1378 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001379#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001380 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1381 usb_stor_buf[3]);
1382 if (usb_test_unit_ready(pccb, ss)) {
1383 printf("Device NOT ready\n"
1384 " Request Sense returned %02X %02X %02X\n",
1385 pccb->sense_buf[2], pccb->sense_buf[12],
1386 pccb->sense_buf[13]);
1387 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001388 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001389 return 1;
1390 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001391 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001392 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001393 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001394 memset(pccb->pdata, 0, 8);
1395 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001396 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001397 cap[0] = 2880;
1398 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001399 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001400 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1401 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001402#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001403 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1404 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001405#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001406 cap[0] = cpu_to_be32(cap[0]);
1407 cap[1] = cpu_to_be32(cap[1]);
1408
wdenk149dded2003-09-10 18:20:28 +00001409 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001410 cap[0] += 1;
1411 capacity = &cap[0];
1412 blksz = &cap[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001413 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1414 *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001415 dev_desc->lba = *capacity;
1416 dev_desc->blksz = *blksz;
1417 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001418 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1419 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001420
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001421 /*
1422 * The U-Boot EHCI driver cannot handle more than 4096 * 5 bytes in a
1423 * transfer without running itself out of qt_buffers.
1424 */
1425 ss->max_xfer_blk = (4096 * 5) / dev_desc->blksz;
1426
wdenkaffae2b2002-08-17 09:36:01 +00001427 init_part(dev_desc);
1428
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001429 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001430 return 1;
1431}