blob: 16667f3948253d2b42d0101fbac6f3cc97fb1cf1 [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 USB_STOR_DEBUG
60#undef BBB_COMDAT_TRACE
61#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000062
63#ifdef USB_STOR_DEBUG
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010064#define USB_STOR_PRINTF(fmt, args...) printf(fmt , ##args)
wdenkaffae2b2002-08-17 09:36:01 +000065#else
Wolfgang Denkf092f152011-10-04 21:19:19 +020066#define USB_STOR_PRINTF(fmt, args...)
wdenkaffae2b2002-08-17 09:36:01 +000067#endif
68
69#include <scsi.h>
70/* direction table -- this indicates the direction of the data
71 * transfer for each command code -- a 1 indicates input
72 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040073static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000074 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
75 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
78};
79#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
80
81static unsigned char usb_stor_buf[512];
82static ccb usb_ccb;
83
84/*
85 * CBI style
86 */
87
88#define US_CBI_ADSC 0
89
wdenk149dded2003-09-10 18:20:28 +000090/*
91 * BULK only
92 */
93#define US_BBB_RESET 0xff
94#define US_BBB_GET_MAX_LUN 0xfe
95
96/* Command Block Wrapper */
97typedef struct {
98 __u32 dCBWSignature;
99# define CBWSIGNATURE 0x43425355
100 __u32 dCBWTag;
101 __u32 dCBWDataTransferLength;
102 __u8 bCBWFlags;
103# define CBWFLAGS_OUT 0x00
104# define CBWFLAGS_IN 0x80
105 __u8 bCBWLUN;
106 __u8 bCDBLength;
107# define CBWCDBLENGTH 16
108 __u8 CBWCDB[CBWCDBLENGTH];
109} umass_bbb_cbw_t;
wdenk80885a92004-02-26 23:46:20 +0000110#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100111static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +0000112
113/* Command Status Wrapper */
114typedef struct {
115 __u32 dCSWSignature;
116# define CSWSIGNATURE 0x53425355
117 __u32 dCSWTag;
118 __u32 dCSWDataResidue;
119 __u8 bCSWStatus;
120# define CSWSTATUS_GOOD 0x0
wdenk80885a92004-02-26 23:46:20 +0000121# define CSWSTATUS_FAILED 0x1
wdenk149dded2003-09-10 18:20:28 +0000122# define CSWSTATUS_PHASE 0x2
123} umass_bbb_csw_t;
wdenk80885a92004-02-26 23:46:20 +0000124#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000125
126#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100127static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000128
129static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
130
131struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100132typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
133typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000134
135struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100136 struct usb_device *pusb_dev; /* this usb_device */
137
138 unsigned int flags; /* from filter initially */
139 unsigned char ifnum; /* interface number */
140 unsigned char ep_in; /* in endpoint */
141 unsigned char ep_out; /* out ....... */
142 unsigned char ep_int; /* interrupt . */
143 unsigned char subclass; /* as in overview */
144 unsigned char protocol; /* .............. */
145 unsigned char attention_done; /* force attn on first cmd */
146 unsigned short ip_data; /* interrupt data */
147 int action; /* what to do */
148 int ip_wanted; /* needed */
149 int *irq_handle; /* for USB int requests */
150 unsigned int irqpipe; /* pipe for release_irq */
151 unsigned char irqmaxp; /* max packed for irq Pipe */
152 unsigned char irqinterval; /* Intervall for IRQ Pipe */
153 ccb *srb; /* current srb */
154 trans_reset transport_reset; /* reset routine */
155 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000156};
157
158static struct us_data usb_stor[USB_MAX_STOR_DEV];
159
160
wdenk80885a92004-02-26 23:46:20 +0000161#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000162#define USB_STOR_TRANSPORT_FAILED -1
163#define USB_STOR_TRANSPORT_ERROR -2
164
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100165int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
166 block_dev_desc_t *dev_desc);
167int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
168 struct us_data *ss);
169unsigned long usb_stor_read(int device, unsigned long blknr,
170 unsigned long blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530171unsigned long usb_stor_write(int device, unsigned long blknr,
172 unsigned long blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000173struct usb_device * usb_get_dev_index(int index);
174void uhci_show_temp_int_td(void);
175
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000176#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000177block_dev_desc_t *usb_stor_get_dev(int index)
178{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200179 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000180}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000181#endif
wdenkaffae2b2002-08-17 09:36:01 +0000182
183void usb_show_progress(void)
184{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200185 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000186}
187
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100188/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200189 * show info on storage devices; 'usb start/init' must be invoked earlier
190 * as we only retrieve structures populated during devices initialization
191 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100192int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200193{
194 int i;
195
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100196 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200197 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100198 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200199 dev_print(&usb_dev_desc[i]);
200 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100201 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100202 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700203
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100204 printf("No storage devices, perhaps not 'usb start'ed..?\n");
205 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200206}
207
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200208static unsigned int usb_get_max_lun(struct us_data *us)
209{
210 int len;
211 unsigned char result;
212 len = usb_control_msg(us->pusb_dev,
213 usb_rcvctrlpipe(us->pusb_dev, 0),
214 US_BBB_GET_MAX_LUN,
215 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
216 0, us->ifnum,
217 &result, sizeof(result),
218 USB_CNTL_TIMEOUT * 5);
219 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
220 len, (int) result);
221 return (len > 0) ? result : 0;
222}
223
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100224/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200225 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000226 * to the user if mode = 1
227 * returns current device or -1 if no
228 */
229int usb_stor_scan(int mode)
230{
231 unsigned char i;
232 struct usb_device *dev;
233
wdenk149dded2003-09-10 18:20:28 +0000234 /* GJ */
235 memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
236
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100237 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200238 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100239
wdenkaffae2b2002-08-17 09:36:01 +0000240 usb_disable_asynch(1); /* asynch transfer not allowed */
241
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100242 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
243 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 usb_dev_desc[i].if_type = IF_TYPE_USB;
245 usb_dev_desc[i].dev = i;
246 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200247 usb_dev_desc[i].target = 0xff;
248 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100249 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530250 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000251 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200252
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100253 usb_max_devs = 0;
254 for (i = 0; i < USB_MAX_DEVICE; i++) {
255 dev = usb_get_dev_index(i); /* get device */
256 USB_STOR_PRINTF("i=%d\n", i);
257 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100258 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100259
260 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200261 /* OK, it's a storage device. Iterate over its LUNs
262 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100263 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200264 int lun, max_lun, start = usb_max_devs;
265
266 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
267 for (lun = 0;
268 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
269 lun++) {
270 usb_dev_desc[usb_max_devs].lun = lun;
271 if (usb_stor_get_info(dev, &usb_stor[start],
272 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000273 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100274 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200275 }
276 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100277 /* if storage device */
278 if (usb_max_devs == USB_MAX_STOR_DEV) {
279 printf("max USB Storage Device reached: %d stopping\n",
280 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000281 break;
282 }
283 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200284
wdenkaffae2b2002-08-17 09:36:01 +0000285 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200286 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100287 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000288 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100289 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000290}
291
292static int usb_stor_irq(struct usb_device *dev)
293{
294 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100295 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000296
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100297 if (us->ip_wanted)
298 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000299 return 0;
300}
301
302
303#ifdef USB_STOR_DEBUG
304
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100305static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000306{
307 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100308 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
309 for (i = 0; i < 12; i++)
310 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000311 printf("\n");
312}
313
314static void display_int_status(unsigned long tmp)
315{
316 printf("Status: %s %s %s %s %s %s %s\n",
317 (tmp & USB_ST_ACTIVE) ? "Active" : "",
318 (tmp & USB_ST_STALLED) ? "Stalled" : "",
319 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
320 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
321 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
322 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
323 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
324}
325#endif
326/***********************************************************************
327 * Data transfer routines
328 ***********************************************************************/
329
330static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
331{
332 int max_size;
333 int this_xfer;
334 int result;
335 int partial;
336 int maxtry;
337 int stat;
338
339 /* determine the maximum packet size for these transfers */
340 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
341
342 /* while we have data left to transfer */
343 while (length) {
344
345 /* calculate how long this will be -- maximum or a remainder */
346 this_xfer = length > max_size ? max_size : length;
347 length -= this_xfer;
348
349 /* setup the retry counter */
350 maxtry = 10;
351
352 /* set up the transfer loop */
353 do {
354 /* transfer the data */
355 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
356 (unsigned int)buf, this_xfer, 11 - maxtry);
357 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100358 this_xfer, &partial,
359 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000360 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
361 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100362 if (us->pusb_dev->status != 0) {
363 /* if we stall, we need to clear it before
364 * we go on
365 */
wdenkaffae2b2002-08-17 09:36:01 +0000366#ifdef USB_STOR_DEBUG
367 display_int_status(us->pusb_dev->status);
368#endif
369 if (us->pusb_dev->status & USB_ST_STALLED) {
370 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
371 stat = us->pusb_dev->status;
372 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100373 us->pusb_dev->status = stat;
374 if (this_xfer == partial) {
375 USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000376 return 0;
377 }
378 else
379 return result;
380 }
381 if (us->pusb_dev->status & USB_ST_NAK_REC) {
382 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
383 return result;
384 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100385 USB_STOR_PRINTF("bulk transferred with error");
386 if (this_xfer == partial) {
387 USB_STOR_PRINTF(" %d, but data ok\n",
388 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000389 return 0;
390 }
391 /* if our try counter reaches 0, bail out */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100392 USB_STOR_PRINTF(" %d, data %d\n",
393 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000394 if (!maxtry--)
395 return result;
396 }
397 /* update to show what data was transferred */
398 this_xfer -= partial;
399 buf += partial;
400 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100401 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000402 }
403
404 /* if we get here, we're done and successful */
405 return 0;
406}
407
wdenk149dded2003-09-10 18:20:28 +0000408static int usb_stor_BBB_reset(struct us_data *us)
409{
410 int result;
411 unsigned int pipe;
412
413 /*
414 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
415 *
416 * For Reset Recovery the host shall issue in the following order:
417 * a) a Bulk-Only Mass Storage Reset
418 * b) a Clear Feature HALT to the Bulk-In endpoint
419 * c) a Clear Feature HALT to the Bulk-Out endpoint
420 *
421 * This is done in 3 steps.
422 *
423 * If the reset doesn't succeed, the device should be port reset.
424 *
425 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
426 */
427 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100428 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
429 US_BBB_RESET,
430 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
431 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200432
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100433 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000434 USB_STOR_PRINTF("RESET:stall\n");
435 return -1;
436 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200437
wdenk149dded2003-09-10 18:20:28 +0000438 /* long wait for reset */
439 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100440 USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n", result,
441 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000442 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
443 result = usb_clear_halt(us->pusb_dev, pipe);
444 /* long wait for reset */
445 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100446 USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",
447 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000448 /* long wait for reset */
449 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
450 result = usb_clear_halt(us->pusb_dev, pipe);
451 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100452 USB_STOR_PRINTF("BBB_reset result %d: status %X"
453 " clearing OUT endpoint\n", result,
454 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000455 USB_STOR_PRINTF("BBB_reset done\n");
456 return 0;
457}
458
wdenkaffae2b2002-08-17 09:36:01 +0000459/* FIXME: this reset function doesn't really reset the port, and it
460 * should. Actually it should probably do what it's doing here, and
461 * reset the port physically
462 */
463static int usb_stor_CB_reset(struct us_data *us)
464{
465 unsigned char cmd[12];
466 int result;
467
468 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100469 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000470 cmd[0] = SCSI_SEND_DIAG;
471 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100472 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
473 US_CBI_ADSC,
474 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
475 0, us->ifnum, cmd, sizeof(cmd),
476 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000477
478 /* long wait for reset */
479 wait_ms(1500);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100480 USB_STOR_PRINTF("CB_reset result %d: status %X"
481 " clearing endpoint halt\n", result,
482 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000483 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
484 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
485
486 USB_STOR_PRINTF("CB_reset done\n");
487 return 0;
488}
489
wdenk149dded2003-09-10 18:20:28 +0000490/*
491 * Set up the command for a BBB device. Note that the actual SCSI
492 * command is copied into cbw.CBWCDB.
493 */
494int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
495{
496 int result;
497 int actlen;
498 int dir_in;
499 unsigned int pipe;
500 umass_bbb_cbw_t cbw;
501
502 dir_in = US_DIRECTION(srb->cmd[0]);
503
504#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100505 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
506 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
507 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000508 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100509 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000510 printf("cmd[%d] %#x ", result, srb->cmd[result]);
511 printf("\n");
512 }
513#endif
514 /* sanity checks */
515 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
516 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
517 return -1;
518 }
519
520 /* always OUT to the ep */
521 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
522
Christian Eggersc9182612008-05-21 22:12:00 +0200523 cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
524 cbw.dCBWTag = cpu_to_le32(CBWTag++);
525 cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100526 cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
wdenk149dded2003-09-10 18:20:28 +0000527 cbw.bCBWLUN = srb->lun;
528 cbw.bCDBLength = srb->cmdlen;
529 /* copy the command data into the CBW command data buffer */
530 /* DST SRC LEN!!! */
531 memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100532 result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
533 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000534 if (result < 0)
535 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
536 return result;
537}
538
wdenkaffae2b2002-08-17 09:36:01 +0000539/* FIXME: we also need a CBI_command which sets up the completion
540 * interrupt, and waits for it
541 */
542int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
543{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200544 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100545 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000546 unsigned int pipe;
547 unsigned long status;
548
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100549 retry = 5;
550 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000551
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100552 if (dir_in)
553 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
554 else
555 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
556
557 while (retry--) {
558 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000559#ifdef USB_STOR_DEBUG
560 usb_show_srb(srb);
561#endif
562 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100563 result = usb_control_msg(us->pusb_dev,
564 usb_sndctrlpipe(us->pusb_dev , 0),
565 US_CBI_ADSC,
566 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000567 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100568 srb->cmd, srb->cmdlen,
569 USB_CNTL_TIMEOUT * 5);
570 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
571 " status %X\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000572 /* check the return code for the command */
573 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100574 if (us->pusb_dev->status & USB_ST_STALLED) {
575 status = us->pusb_dev->status;
576 USB_STOR_PRINTF(" stall during command found,"
577 " clear pipe\n");
578 usb_clear_halt(us->pusb_dev,
579 usb_sndctrlpipe(us->pusb_dev, 0));
580 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000581 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100582 USB_STOR_PRINTF(" error during command %02X"
583 " Stat = %X\n", srb->cmd[0],
584 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000585 return result;
586 }
587 /* transfer the data payload for this command, if one exists*/
588
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100589 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
590 " direction is %s to go 0x%lx\n", result,
591 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000592 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100593 result = us_one_transfer(us, pipe, (char *)srb->pdata,
594 srb->datalen);
595 USB_STOR_PRINTF("CBI attempted to transfer data,"
596 " result is %d status %lX, len %d\n",
597 result, us->pusb_dev->status,
598 us->pusb_dev->act_len);
599 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000600 break;
601 } /* if (srb->datalen) */
602 else
603 break;
604 }
605 /* return result */
606
607 return result;
608}
609
610
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100611int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000612{
613 int timeout;
614
wdenk80885a92004-02-26 23:46:20 +0000615 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100616 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000617 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
618 timeout = 1000;
619 while (timeout--) {
620 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000621 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100622 wait_ms(10);
wdenkaffae2b2002-08-17 09:36:01 +0000623 }
624 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100625 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000626 us->ip_wanted = 0;
627 return USB_STOR_TRANSPORT_ERROR;
628 }
wdenk80885a92004-02-26 23:46:20 +0000629 USB_STOR_PRINTF
630 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
631 us->ip_data, us->pusb_dev->irq_act_len,
632 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000633 /* UFI gives us ASC and ASCQ, like a request sense */
634 if (us->subclass == US_SC_UFI) {
635 if (srb->cmd[0] == SCSI_REQ_SENSE ||
636 srb->cmd[0] == SCSI_INQUIRY)
637 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000638 else if (us->ip_data)
639 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000640 else
wdenk80885a92004-02-26 23:46:20 +0000641 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000642 }
643 /* otherwise, we interpret the data normally */
644 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000645 case 0x0001:
646 return USB_STOR_TRANSPORT_GOOD;
647 case 0x0002:
648 return USB_STOR_TRANSPORT_FAILED;
649 default:
650 return USB_STOR_TRANSPORT_ERROR;
651 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000652 return USB_STOR_TRANSPORT_ERROR;
653}
654
655#define USB_TRANSPORT_UNKNOWN_RETRY 5
656#define USB_TRANSPORT_NOT_READY_RETRY 10
657
wdenk149dded2003-09-10 18:20:28 +0000658/* clear a stall on an endpoint - special for BBB devices */
659int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
660{
661 int result;
662
663 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100664 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000665 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100666 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000667 return result;
668}
669
670int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
671{
672 int result, retry;
673 int dir_in;
674 int actlen, data_actlen;
675 unsigned int pipe, pipein, pipeout;
676 umass_bbb_csw_t csw;
677#ifdef BBB_XPORT_TRACE
678 unsigned char *ptr;
679 int index;
680#endif
681
682 dir_in = US_DIRECTION(srb->cmd[0]);
683
684 /* COMMAND phase */
685 USB_STOR_PRINTF("COMMAND phase\n");
686 result = usb_stor_BBB_comdat(srb, us);
687 if (result < 0) {
688 USB_STOR_PRINTF("failed to send CBW status %ld\n",
689 us->pusb_dev->status);
690 usb_stor_BBB_reset(us);
691 return USB_STOR_TRANSPORT_FAILED;
692 }
693 wait_ms(5);
694 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
695 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
696 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000697 data_actlen = 0;
698 /* no data, go immediately to the STATUS phase */
699 if (srb->datalen == 0)
700 goto st;
wdenk80885a92004-02-26 23:46:20 +0000701 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000702 if (dir_in)
703 pipe = pipein;
704 else
705 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100706 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
707 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000708 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100709 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000710 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000711 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100712 result = usb_stor_BBB_clear_endpt_stall(us,
713 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000714 if (result >= 0)
715 /* continue on to STATUS phase */
716 goto st;
717 }
718 if (result < 0) {
719 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
720 us->pusb_dev->status);
721 usb_stor_BBB_reset(us);
722 return USB_STOR_TRANSPORT_FAILED;
723 }
724#ifdef BBB_XPORT_TRACE
725 for (index = 0; index < data_actlen; index++)
726 printf("pdata[%d] %#x ", index, srb->pdata[index]);
727 printf("\n");
728#endif
729 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100730st:
wdenk149dded2003-09-10 18:20:28 +0000731 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100732again:
wdenk149dded2003-09-10 18:20:28 +0000733 USB_STOR_PRINTF("STATUS phase\n");
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200734 result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200735 &actlen, USB_CNTL_TIMEOUT*5);
736
wdenk149dded2003-09-10 18:20:28 +0000737 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100738 if ((result < 0) && (retry < 1) &&
739 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000740 USB_STOR_PRINTF("STATUS:stall\n");
741 /* clear the STALL on the endpoint */
742 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
743 if (result >= 0 && (retry++ < 1))
744 /* do a retry */
745 goto again;
746 }
747 if (result < 0) {
748 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
749 us->pusb_dev->status);
750 usb_stor_BBB_reset(us);
751 return USB_STOR_TRANSPORT_FAILED;
752 }
753#ifdef BBB_XPORT_TRACE
754 ptr = (unsigned char *)&csw;
755 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
756 printf("ptr[%d] %#x ", index, ptr[index]);
757 printf("\n");
758#endif
759 /* misuse pipe to get the residue */
Christian Eggersc9182612008-05-21 22:12:00 +0200760 pipe = le32_to_cpu(csw.dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000761 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
762 pipe = srb->datalen - data_actlen;
Christian Eggersc9182612008-05-21 22:12:00 +0200763 if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000764 USB_STOR_PRINTF("!CSWSIGNATURE\n");
765 usb_stor_BBB_reset(us);
766 return USB_STOR_TRANSPORT_FAILED;
Christian Eggersc9182612008-05-21 22:12:00 +0200767 } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000768 USB_STOR_PRINTF("!Tag\n");
769 usb_stor_BBB_reset(us);
770 return USB_STOR_TRANSPORT_FAILED;
771 } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
772 USB_STOR_PRINTF(">PHASE\n");
773 usb_stor_BBB_reset(us);
774 return USB_STOR_TRANSPORT_FAILED;
775 } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
776 USB_STOR_PRINTF("=PHASE\n");
777 usb_stor_BBB_reset(us);
778 return USB_STOR_TRANSPORT_FAILED;
779 } else if (data_actlen > srb->datalen) {
780 USB_STOR_PRINTF("transferred %dB instead of %dB\n",
781 data_actlen, srb->datalen);
782 return USB_STOR_TRANSPORT_FAILED;
783 } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
784 USB_STOR_PRINTF("FAILED\n");
785 return USB_STOR_TRANSPORT_FAILED;
786 }
787
788 return result;
789}
790
wdenkaffae2b2002-08-17 09:36:01 +0000791int usb_stor_CB_transport(ccb *srb, struct us_data *us)
792{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100793 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000794 ccb *psrb;
795 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100796 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000797
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200798 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100799 status = USB_STOR_TRANSPORT_GOOD;
800 retry = 0;
801 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000802 /* issue the command */
803do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100804 result = usb_stor_CB_comdat(srb, us);
805 USB_STOR_PRINTF("command / Data returned %d, status %X\n",
806 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000807 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100808 if (us->protocol == US_PR_CBI) {
809 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000810 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100811 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000812 USB_STOR_PRINTF(" USB CBI Command Error\n");
813 return status;
814 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100815 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
816 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
817 if (!us->ip_data) {
818 /* if the status is good, report it */
819 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000820 USB_STOR_PRINTF(" USB CBI Command Good\n");
821 return status;
822 }
823 }
824 }
825 /* do we have to issue an auto request? */
826 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100827 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
828 USB_STOR_PRINTF("ERROR %X\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000829 us->transport_reset(us);
830 return USB_STOR_TRANSPORT_ERROR;
831 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100832 if ((us->protocol == US_PR_CBI) &&
833 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
834 (srb->cmd[0] == SCSI_INQUIRY))) {
835 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000836 USB_STOR_PRINTF("No auto request and good\n");
837 return USB_STOR_TRANSPORT_GOOD;
838 }
839 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100840 memset(&psrb->cmd[0], 0, 12);
841 psrb->cmd[0] = SCSI_REQ_SENSE;
842 psrb->cmd[1] = srb->lun << 5;
843 psrb->cmd[4] = 18;
844 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200845 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100846 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000847 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 result = usb_stor_CB_comdat(psrb, us);
849 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000850 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100851 if (us->protocol == US_PR_CBI)
852 status = usb_stor_CBI_get_status(psrb, us);
853
854 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
855 USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",
856 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000857 return USB_STOR_TRANSPORT_ERROR;
858 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100859 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
860 srb->sense_buf[0], srb->sense_buf[2],
861 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000862 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100863 if ((srb->sense_buf[2] == 0) &&
864 (srb->sense_buf[12] == 0) &&
865 (srb->sense_buf[13] == 0)) {
866 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000867 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100868 }
869
wdenkaffae2b2002-08-17 09:36:01 +0000870 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100871 switch (srb->sense_buf[2]) {
872 case 0x01:
873 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000874 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000875 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100876 case 0x02:
877 /* Not Ready */
878 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
879 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
880 " 0x%02X (NOT READY)\n", srb->cmd[0],
881 srb->sense_buf[0], srb->sense_buf[2],
882 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000883 return USB_STOR_TRANSPORT_FAILED;
884 } else {
885 wait_ms(100);
886 goto do_retry;
887 }
888 break;
889 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100890 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
891 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
892 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
893 srb->sense_buf[2], srb->sense_buf[12],
894 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000895 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100896 } else
wdenk149dded2003-09-10 18:20:28 +0000897 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000898 break;
wdenkaffae2b2002-08-17 09:36:01 +0000899 }
900 return USB_STOR_TRANSPORT_FAILED;
901}
902
903
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100904static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000905{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906 int retry, i;
907 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000908 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100909 memset(&srb->cmd[0], 0, 12);
910 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200911 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100912 srb->cmd[4] = 36;
913 srb->datalen = 36;
914 srb->cmdlen = 12;
915 i = ss->transport(srb, ss);
916 USB_STOR_PRINTF("inquiry returns %d\n", i);
917 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000918 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200919 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000920
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100921 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000922 printf("error in inquiry\n");
923 return -1;
924 }
925 return 0;
926}
927
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100928static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000929{
930 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000931
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100932 ptr = (char *)srb->pdata;
933 memset(&srb->cmd[0], 0, 12);
934 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200935 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100936 srb->cmd[4] = 18;
937 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200938 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100939 srb->cmdlen = 12;
940 ss->transport(srb, ss);
941 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
942 srb->sense_buf[2], srb->sense_buf[12],
943 srb->sense_buf[13]);
944 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000945 return 0;
946}
947
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100948static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000949{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200950 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000951
wdenkaffae2b2002-08-17 09:36:01 +0000952 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100953 memset(&srb->cmd[0], 0, 12);
954 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200955 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100956 srb->datalen = 0;
957 srb->cmdlen = 12;
958 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000959 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100960 usb_request_sense(srb, ss);
961 wait_ms(100);
962 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000963
wdenkaffae2b2002-08-17 09:36:01 +0000964 return -1;
965}
966
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000968{
969 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100970 /* XXX retries */
971 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000972 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100973 memset(&srb->cmd[0], 0, 12);
974 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200975 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 srb->datalen = 8;
977 srb->cmdlen = 12;
978 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000979 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100980 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000981
wdenkaffae2b2002-08-17 09:36:01 +0000982 return -1;
983}
984
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100985static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
986 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000987{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100988 memset(&srb->cmd[0], 0, 12);
989 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200990 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100991 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
992 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
993 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
994 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
995 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
996 srb->cmd[8] = (unsigned char) blocks & 0xff;
997 srb->cmdlen = 12;
998 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
999 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001000}
1001
Mahavir Jain127e1082009-11-03 12:22:10 +05301002static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1003 unsigned short blocks)
1004{
1005 memset(&srb->cmd[0], 0, 12);
1006 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001007 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301008 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1009 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1010 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1011 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1012 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1013 srb->cmd[8] = (unsigned char) blocks & 0xff;
1014 srb->cmdlen = 12;
1015 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1016 return ss->transport(srb, ss);
1017}
1018
wdenkaffae2b2002-08-17 09:36:01 +00001019
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001020#ifdef CONFIG_USB_BIN_FIXUP
1021/*
1022 * Some USB storage devices queried for SCSI identification data respond with
1023 * binary strings, which if output to the console freeze the terminal. The
1024 * workaround is to modify the vendor and product strings read from such
1025 * device with proper values (as reported by 'usb info').
1026 *
1027 * Vendor and product length limits are taken from the definition of
1028 * block_dev_desc_t in include/part.h.
1029 */
1030static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1031 unsigned char vendor[],
1032 unsigned char product[]) {
1033 const unsigned char max_vendor_len = 40;
1034 const unsigned char max_product_len = 20;
1035 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001036 strncpy((char *)vendor, "SMSC", max_vendor_len);
1037 strncpy((char *)product, "Flash Media Cntrller",
1038 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001039 }
1040}
1041#endif /* CONFIG_USB_BIN_FIXUP */
1042
wdenkaffae2b2002-08-17 09:36:01 +00001043#define USB_MAX_READ_BLK 20
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;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001051 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001052 ccb *srb = &usb_ccb;
1053
1054 if (blkcnt == 0)
1055 return 0;
1056
1057 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001058 /* Setup device */
1059 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1060 dev = NULL;
1061 for (i = 0; i < USB_MAX_DEVICE; i++) {
1062 dev = usb_get_dev_index(i);
1063 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001064 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001065 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001066 break;
1067 }
1068
1069 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001070 srb->lun = usb_dev_desc[device].lun;
1071 buf_addr = (unsigned long)buffer;
1072 start = blknr;
1073 blks = blkcnt;
1074 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1075 printf("Device NOT ready\n Request Sense returned %02X %02X"
1076 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1077 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001078 return 0;
1079 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001080
1081 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1082 " buffer %lx\n", device, start, blks, buf_addr);
1083
wdenkaffae2b2002-08-17 09:36:01 +00001084 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001085 /* XXX need some comment here */
1086 retry = 2;
1087 srb->pdata = (unsigned char *)buf_addr;
1088 if (blks > USB_MAX_READ_BLK)
1089 smallblks = USB_MAX_READ_BLK;
1090 else
1091 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001092retry_it:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001093 if (smallblks == USB_MAX_READ_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001094 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001095 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1096 srb->pdata = (unsigned char *)buf_addr;
1097 if (usb_read_10(srb, (struct us_data *)dev->privptr, start,
1098 smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001099 USB_STOR_PRINTF("Read ERROR\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001100 usb_request_sense(srb, (struct us_data *)dev->privptr);
1101 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001102 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001103 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001104 break;
1105 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001106 start += smallblks;
1107 blks -= smallblks;
1108 buf_addr += srb->datalen;
1109 } while (blks != 0);
1110
1111 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1112 start, smallblks, buf_addr);
1113
wdenkaffae2b2002-08-17 09:36:01 +00001114 usb_disable_asynch(0); /* asynch transfer allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001115 if (blkcnt >= USB_MAX_READ_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001116 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001117 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001118}
1119
Mahavir Jain127e1082009-11-03 12:22:10 +05301120#define USB_MAX_WRITE_BLK 20
1121
1122unsigned long usb_stor_write(int device, unsigned long blknr,
1123 unsigned long blkcnt, const void *buffer)
1124{
1125 unsigned long start, blks, buf_addr;
1126 unsigned short smallblks;
1127 struct usb_device *dev;
1128 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 }
1145
1146 usb_disable_asynch(1); /* asynch transfer not allowed */
1147
1148 srb->lun = usb_dev_desc[device].lun;
1149 buf_addr = (unsigned long)buffer;
1150 start = blknr;
1151 blks = blkcnt;
1152 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1153 printf("Device NOT ready\n Request Sense returned %02X %02X"
1154 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1155 srb->sense_buf[13]);
1156 return 0;
1157 }
1158
1159 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1160 " buffer %lx\n", device, start, blks, buf_addr);
1161
1162 do {
1163 /* If write fails retry for max retry count else
1164 * return with number of blocks written successfully.
1165 */
1166 retry = 2;
1167 srb->pdata = (unsigned char *)buf_addr;
1168 if (blks > USB_MAX_WRITE_BLK)
1169 smallblks = USB_MAX_WRITE_BLK;
1170 else
1171 smallblks = (unsigned short) blks;
1172retry_it:
1173 if (smallblks == USB_MAX_WRITE_BLK)
1174 usb_show_progress();
1175 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1176 srb->pdata = (unsigned char *)buf_addr;
1177 if (usb_write_10(srb, (struct us_data *)dev->privptr, start,
1178 smallblks)) {
1179 USB_STOR_PRINTF("Write ERROR\n");
1180 usb_request_sense(srb, (struct us_data *)dev->privptr);
1181 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 */
1195 if (blkcnt >= USB_MAX_WRITE_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
1421 init_part(dev_desc);
1422
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001423 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001424 return 1;
1425}