blob: 6963e6dcc89458f92a4c6f2148d5c019aed29972 [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
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +010066#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
176block_dev_desc_t *usb_stor_get_dev(int index)
177{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200178 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000179}
180
181
182void usb_show_progress(void)
183{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200184 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000185}
186
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100187/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200188 * show info on storage devices; 'usb start/init' must be invoked earlier
189 * as we only retrieve structures populated during devices initialization
190 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100191int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200192{
193 int i;
194
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100195 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200196 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100197 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200198 dev_print(&usb_dev_desc[i]);
199 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100200 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100201 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700202
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100203 printf("No storage devices, perhaps not 'usb start'ed..?\n");
204 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200205}
206
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200207static unsigned int usb_get_max_lun(struct us_data *us)
208{
209 int len;
210 unsigned char result;
211 len = usb_control_msg(us->pusb_dev,
212 usb_rcvctrlpipe(us->pusb_dev, 0),
213 US_BBB_GET_MAX_LUN,
214 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
215 0, us->ifnum,
216 &result, sizeof(result),
217 USB_CNTL_TIMEOUT * 5);
218 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
219 len, (int) result);
220 return (len > 0) ? result : 0;
221}
222
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100223/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200224 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000225 * to the user if mode = 1
226 * returns current device or -1 if no
227 */
228int usb_stor_scan(int mode)
229{
230 unsigned char i;
231 struct usb_device *dev;
232
wdenk149dded2003-09-10 18:20:28 +0000233 /* GJ */
234 memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
235
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100236 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200237 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100238
wdenkaffae2b2002-08-17 09:36:01 +0000239 usb_disable_asynch(1); /* asynch transfer not allowed */
240
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100241 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
242 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100243 usb_dev_desc[i].if_type = IF_TYPE_USB;
244 usb_dev_desc[i].dev = i;
245 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200246 usb_dev_desc[i].target = 0xff;
247 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100248 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530249 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000250 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200251
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100252 usb_max_devs = 0;
253 for (i = 0; i < USB_MAX_DEVICE; i++) {
254 dev = usb_get_dev_index(i); /* get device */
255 USB_STOR_PRINTF("i=%d\n", i);
256 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +0000257 break; /* no more devices avaiable */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100258
259 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200260 /* OK, it's a storage device. Iterate over its LUNs
261 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100262 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200263 int lun, max_lun, start = usb_max_devs;
264
265 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
266 for (lun = 0;
267 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
268 lun++) {
269 usb_dev_desc[usb_max_devs].lun = lun;
270 if (usb_stor_get_info(dev, &usb_stor[start],
271 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000272 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100273 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200274 }
275 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100276 /* if storage device */
277 if (usb_max_devs == USB_MAX_STOR_DEV) {
278 printf("max USB Storage Device reached: %d stopping\n",
279 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000280 break;
281 }
282 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200283
wdenkaffae2b2002-08-17 09:36:01 +0000284 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200285 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100286 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000287 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100288 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000289}
290
291static int usb_stor_irq(struct usb_device *dev)
292{
293 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100294 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000295
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100296 if (us->ip_wanted)
297 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000298 return 0;
299}
300
301
302#ifdef USB_STOR_DEBUG
303
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100304static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000305{
306 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100307 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
308 for (i = 0; i < 12; i++)
309 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000310 printf("\n");
311}
312
313static void display_int_status(unsigned long tmp)
314{
315 printf("Status: %s %s %s %s %s %s %s\n",
316 (tmp & USB_ST_ACTIVE) ? "Active" : "",
317 (tmp & USB_ST_STALLED) ? "Stalled" : "",
318 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
319 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
320 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
321 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
322 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
323}
324#endif
325/***********************************************************************
326 * Data transfer routines
327 ***********************************************************************/
328
329static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
330{
331 int max_size;
332 int this_xfer;
333 int result;
334 int partial;
335 int maxtry;
336 int stat;
337
338 /* determine the maximum packet size for these transfers */
339 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
340
341 /* while we have data left to transfer */
342 while (length) {
343
344 /* calculate how long this will be -- maximum or a remainder */
345 this_xfer = length > max_size ? max_size : length;
346 length -= this_xfer;
347
348 /* setup the retry counter */
349 maxtry = 10;
350
351 /* set up the transfer loop */
352 do {
353 /* transfer the data */
354 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
355 (unsigned int)buf, this_xfer, 11 - maxtry);
356 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100357 this_xfer, &partial,
358 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000359 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
360 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100361 if (us->pusb_dev->status != 0) {
362 /* if we stall, we need to clear it before
363 * we go on
364 */
wdenkaffae2b2002-08-17 09:36:01 +0000365#ifdef USB_STOR_DEBUG
366 display_int_status(us->pusb_dev->status);
367#endif
368 if (us->pusb_dev->status & USB_ST_STALLED) {
369 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
370 stat = us->pusb_dev->status;
371 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100372 us->pusb_dev->status = stat;
373 if (this_xfer == partial) {
374 USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000375 return 0;
376 }
377 else
378 return result;
379 }
380 if (us->pusb_dev->status & USB_ST_NAK_REC) {
381 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
382 return result;
383 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100384 USB_STOR_PRINTF("bulk transferred with error");
385 if (this_xfer == partial) {
386 USB_STOR_PRINTF(" %d, but data ok\n",
387 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000388 return 0;
389 }
390 /* if our try counter reaches 0, bail out */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100391 USB_STOR_PRINTF(" %d, data %d\n",
392 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000393 if (!maxtry--)
394 return result;
395 }
396 /* update to show what data was transferred */
397 this_xfer -= partial;
398 buf += partial;
399 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100400 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000401 }
402
403 /* if we get here, we're done and successful */
404 return 0;
405}
406
wdenk149dded2003-09-10 18:20:28 +0000407static int usb_stor_BBB_reset(struct us_data *us)
408{
409 int result;
410 unsigned int pipe;
411
412 /*
413 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
414 *
415 * For Reset Recovery the host shall issue in the following order:
416 * a) a Bulk-Only Mass Storage Reset
417 * b) a Clear Feature HALT to the Bulk-In endpoint
418 * c) a Clear Feature HALT to the Bulk-Out endpoint
419 *
420 * This is done in 3 steps.
421 *
422 * If the reset doesn't succeed, the device should be port reset.
423 *
424 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
425 */
426 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100427 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
428 US_BBB_RESET,
429 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
430 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200431
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100432 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000433 USB_STOR_PRINTF("RESET:stall\n");
434 return -1;
435 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200436
wdenk149dded2003-09-10 18:20:28 +0000437 /* long wait for reset */
438 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100439 USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n", result,
440 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000441 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
442 result = usb_clear_halt(us->pusb_dev, pipe);
443 /* long wait for reset */
444 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100445 USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",
446 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000447 /* long wait for reset */
448 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
449 result = usb_clear_halt(us->pusb_dev, pipe);
450 wait_ms(150);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100451 USB_STOR_PRINTF("BBB_reset result %d: status %X"
452 " clearing OUT endpoint\n", result,
453 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000454 USB_STOR_PRINTF("BBB_reset done\n");
455 return 0;
456}
457
wdenkaffae2b2002-08-17 09:36:01 +0000458/* FIXME: this reset function doesn't really reset the port, and it
459 * should. Actually it should probably do what it's doing here, and
460 * reset the port physically
461 */
462static int usb_stor_CB_reset(struct us_data *us)
463{
464 unsigned char cmd[12];
465 int result;
466
467 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100468 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000469 cmd[0] = SCSI_SEND_DIAG;
470 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100471 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
472 US_CBI_ADSC,
473 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
474 0, us->ifnum, cmd, sizeof(cmd),
475 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000476
477 /* long wait for reset */
478 wait_ms(1500);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100479 USB_STOR_PRINTF("CB_reset result %d: status %X"
480 " clearing endpoint halt\n", result,
481 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000482 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
483 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
484
485 USB_STOR_PRINTF("CB_reset done\n");
486 return 0;
487}
488
wdenk149dded2003-09-10 18:20:28 +0000489/*
490 * Set up the command for a BBB device. Note that the actual SCSI
491 * command is copied into cbw.CBWCDB.
492 */
493int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
494{
495 int result;
496 int actlen;
497 int dir_in;
498 unsigned int pipe;
499 umass_bbb_cbw_t cbw;
500
501 dir_in = US_DIRECTION(srb->cmd[0]);
502
503#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100504 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
505 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
506 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000507 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000509 printf("cmd[%d] %#x ", result, srb->cmd[result]);
510 printf("\n");
511 }
512#endif
513 /* sanity checks */
514 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
515 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
516 return -1;
517 }
518
519 /* always OUT to the ep */
520 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
521
Christian Eggersc9182612008-05-21 22:12:00 +0200522 cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
523 cbw.dCBWTag = cpu_to_le32(CBWTag++);
524 cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100525 cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
wdenk149dded2003-09-10 18:20:28 +0000526 cbw.bCBWLUN = srb->lun;
527 cbw.bCDBLength = srb->cmdlen;
528 /* copy the command data into the CBW command data buffer */
529 /* DST SRC LEN!!! */
530 memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100531 result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
532 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000533 if (result < 0)
534 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
535 return result;
536}
537
wdenkaffae2b2002-08-17 09:36:01 +0000538/* FIXME: we also need a CBI_command which sets up the completion
539 * interrupt, and waits for it
540 */
541int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
542{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200543 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100544 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000545 unsigned int pipe;
546 unsigned long status;
547
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100548 retry = 5;
549 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000550
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100551 if (dir_in)
552 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
553 else
554 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
555
556 while (retry--) {
557 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000558#ifdef USB_STOR_DEBUG
559 usb_show_srb(srb);
560#endif
561 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100562 result = usb_control_msg(us->pusb_dev,
563 usb_sndctrlpipe(us->pusb_dev , 0),
564 US_CBI_ADSC,
565 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000566 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100567 srb->cmd, srb->cmdlen,
568 USB_CNTL_TIMEOUT * 5);
569 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
570 " status %X\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000571 /* check the return code for the command */
572 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100573 if (us->pusb_dev->status & USB_ST_STALLED) {
574 status = us->pusb_dev->status;
575 USB_STOR_PRINTF(" stall during command found,"
576 " clear pipe\n");
577 usb_clear_halt(us->pusb_dev,
578 usb_sndctrlpipe(us->pusb_dev, 0));
579 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000580 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100581 USB_STOR_PRINTF(" error during command %02X"
582 " Stat = %X\n", srb->cmd[0],
583 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000584 return result;
585 }
586 /* transfer the data payload for this command, if one exists*/
587
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100588 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
589 " direction is %s to go 0x%lx\n", result,
590 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000591 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100592 result = us_one_transfer(us, pipe, (char *)srb->pdata,
593 srb->datalen);
594 USB_STOR_PRINTF("CBI attempted to transfer data,"
595 " result is %d status %lX, len %d\n",
596 result, us->pusb_dev->status,
597 us->pusb_dev->act_len);
598 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000599 break;
600 } /* if (srb->datalen) */
601 else
602 break;
603 }
604 /* return result */
605
606 return result;
607}
608
609
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100610int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000611{
612 int timeout;
613
wdenk80885a92004-02-26 23:46:20 +0000614 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100615 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000616 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
617 timeout = 1000;
618 while (timeout--) {
619 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000620 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100621 wait_ms(10);
wdenkaffae2b2002-08-17 09:36:01 +0000622 }
623 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100624 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000625 us->ip_wanted = 0;
626 return USB_STOR_TRANSPORT_ERROR;
627 }
wdenk80885a92004-02-26 23:46:20 +0000628 USB_STOR_PRINTF
629 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
630 us->ip_data, us->pusb_dev->irq_act_len,
631 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000632 /* UFI gives us ASC and ASCQ, like a request sense */
633 if (us->subclass == US_SC_UFI) {
634 if (srb->cmd[0] == SCSI_REQ_SENSE ||
635 srb->cmd[0] == SCSI_INQUIRY)
636 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000637 else if (us->ip_data)
638 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000639 else
wdenk80885a92004-02-26 23:46:20 +0000640 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000641 }
642 /* otherwise, we interpret the data normally */
643 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000644 case 0x0001:
645 return USB_STOR_TRANSPORT_GOOD;
646 case 0x0002:
647 return USB_STOR_TRANSPORT_FAILED;
648 default:
649 return USB_STOR_TRANSPORT_ERROR;
650 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000651 return USB_STOR_TRANSPORT_ERROR;
652}
653
654#define USB_TRANSPORT_UNKNOWN_RETRY 5
655#define USB_TRANSPORT_NOT_READY_RETRY 10
656
wdenk149dded2003-09-10 18:20:28 +0000657/* clear a stall on an endpoint - special for BBB devices */
658int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
659{
660 int result;
661
662 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100663 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000664 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100665 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000666 return result;
667}
668
669int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
670{
671 int result, retry;
672 int dir_in;
673 int actlen, data_actlen;
674 unsigned int pipe, pipein, pipeout;
675 umass_bbb_csw_t csw;
676#ifdef BBB_XPORT_TRACE
677 unsigned char *ptr;
678 int index;
679#endif
680
681 dir_in = US_DIRECTION(srb->cmd[0]);
682
683 /* COMMAND phase */
684 USB_STOR_PRINTF("COMMAND phase\n");
685 result = usb_stor_BBB_comdat(srb, us);
686 if (result < 0) {
687 USB_STOR_PRINTF("failed to send CBW status %ld\n",
688 us->pusb_dev->status);
689 usb_stor_BBB_reset(us);
690 return USB_STOR_TRANSPORT_FAILED;
691 }
692 wait_ms(5);
693 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
694 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
695 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000696 data_actlen = 0;
697 /* no data, go immediately to the STATUS phase */
698 if (srb->datalen == 0)
699 goto st;
wdenk80885a92004-02-26 23:46:20 +0000700 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000701 if (dir_in)
702 pipe = pipein;
703 else
704 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100705 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
706 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000707 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100708 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000709 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000710 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100711 result = usb_stor_BBB_clear_endpt_stall(us,
712 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000713 if (result >= 0)
714 /* continue on to STATUS phase */
715 goto st;
716 }
717 if (result < 0) {
718 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
719 us->pusb_dev->status);
720 usb_stor_BBB_reset(us);
721 return USB_STOR_TRANSPORT_FAILED;
722 }
723#ifdef BBB_XPORT_TRACE
724 for (index = 0; index < data_actlen; index++)
725 printf("pdata[%d] %#x ", index, srb->pdata[index]);
726 printf("\n");
727#endif
728 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100729st:
wdenk149dded2003-09-10 18:20:28 +0000730 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100731again:
wdenk149dded2003-09-10 18:20:28 +0000732 USB_STOR_PRINTF("STATUS phase\n");
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200733 result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200734 &actlen, USB_CNTL_TIMEOUT*5);
735
wdenk149dded2003-09-10 18:20:28 +0000736 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100737 if ((result < 0) && (retry < 1) &&
738 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000739 USB_STOR_PRINTF("STATUS:stall\n");
740 /* clear the STALL on the endpoint */
741 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
742 if (result >= 0 && (retry++ < 1))
743 /* do a retry */
744 goto again;
745 }
746 if (result < 0) {
747 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
748 us->pusb_dev->status);
749 usb_stor_BBB_reset(us);
750 return USB_STOR_TRANSPORT_FAILED;
751 }
752#ifdef BBB_XPORT_TRACE
753 ptr = (unsigned char *)&csw;
754 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
755 printf("ptr[%d] %#x ", index, ptr[index]);
756 printf("\n");
757#endif
758 /* misuse pipe to get the residue */
Christian Eggersc9182612008-05-21 22:12:00 +0200759 pipe = le32_to_cpu(csw.dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000760 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
761 pipe = srb->datalen - data_actlen;
Christian Eggersc9182612008-05-21 22:12:00 +0200762 if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000763 USB_STOR_PRINTF("!CSWSIGNATURE\n");
764 usb_stor_BBB_reset(us);
765 return USB_STOR_TRANSPORT_FAILED;
Christian Eggersc9182612008-05-21 22:12:00 +0200766 } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000767 USB_STOR_PRINTF("!Tag\n");
768 usb_stor_BBB_reset(us);
769 return USB_STOR_TRANSPORT_FAILED;
770 } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
771 USB_STOR_PRINTF(">PHASE\n");
772 usb_stor_BBB_reset(us);
773 return USB_STOR_TRANSPORT_FAILED;
774 } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
775 USB_STOR_PRINTF("=PHASE\n");
776 usb_stor_BBB_reset(us);
777 return USB_STOR_TRANSPORT_FAILED;
778 } else if (data_actlen > srb->datalen) {
779 USB_STOR_PRINTF("transferred %dB instead of %dB\n",
780 data_actlen, srb->datalen);
781 return USB_STOR_TRANSPORT_FAILED;
782 } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
783 USB_STOR_PRINTF("FAILED\n");
784 return USB_STOR_TRANSPORT_FAILED;
785 }
786
787 return result;
788}
789
wdenkaffae2b2002-08-17 09:36:01 +0000790int usb_stor_CB_transport(ccb *srb, struct us_data *us)
791{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100792 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000793 ccb *psrb;
794 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100795 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000796
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200797 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100798 status = USB_STOR_TRANSPORT_GOOD;
799 retry = 0;
800 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000801 /* issue the command */
802do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100803 result = usb_stor_CB_comdat(srb, us);
804 USB_STOR_PRINTF("command / Data returned %d, status %X\n",
805 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000806 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100807 if (us->protocol == US_PR_CBI) {
808 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000809 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100810 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000811 USB_STOR_PRINTF(" USB CBI Command Error\n");
812 return status;
813 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100814 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
815 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
816 if (!us->ip_data) {
817 /* if the status is good, report it */
818 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000819 USB_STOR_PRINTF(" USB CBI Command Good\n");
820 return status;
821 }
822 }
823 }
824 /* do we have to issue an auto request? */
825 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100826 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
827 USB_STOR_PRINTF("ERROR %X\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000828 us->transport_reset(us);
829 return USB_STOR_TRANSPORT_ERROR;
830 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100831 if ((us->protocol == US_PR_CBI) &&
832 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
833 (srb->cmd[0] == SCSI_INQUIRY))) {
834 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000835 USB_STOR_PRINTF("No auto request and good\n");
836 return USB_STOR_TRANSPORT_GOOD;
837 }
838 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100839 memset(&psrb->cmd[0], 0, 12);
840 psrb->cmd[0] = SCSI_REQ_SENSE;
841 psrb->cmd[1] = srb->lun << 5;
842 psrb->cmd[4] = 18;
843 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200844 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100845 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000846 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100847 result = usb_stor_CB_comdat(psrb, us);
848 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000849 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 if (us->protocol == US_PR_CBI)
851 status = usb_stor_CBI_get_status(psrb, us);
852
853 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
854 USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",
855 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000856 return USB_STOR_TRANSPORT_ERROR;
857 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100858 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
859 srb->sense_buf[0], srb->sense_buf[2],
860 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000861 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100862 if ((srb->sense_buf[2] == 0) &&
863 (srb->sense_buf[12] == 0) &&
864 (srb->sense_buf[13] == 0)) {
865 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000866 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100867 }
868
wdenkaffae2b2002-08-17 09:36:01 +0000869 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 switch (srb->sense_buf[2]) {
871 case 0x01:
872 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000873 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000874 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100875 case 0x02:
876 /* Not Ready */
877 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
878 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
879 " 0x%02X (NOT READY)\n", srb->cmd[0],
880 srb->sense_buf[0], srb->sense_buf[2],
881 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000882 return USB_STOR_TRANSPORT_FAILED;
883 } else {
884 wait_ms(100);
885 goto do_retry;
886 }
887 break;
888 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100889 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
890 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
891 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
892 srb->sense_buf[2], srb->sense_buf[12],
893 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000894 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100895 } else
wdenk149dded2003-09-10 18:20:28 +0000896 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000897 break;
wdenkaffae2b2002-08-17 09:36:01 +0000898 }
899 return USB_STOR_TRANSPORT_FAILED;
900}
901
902
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100903static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000904{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100905 int retry, i;
906 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000907 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908 memset(&srb->cmd[0], 0, 12);
909 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200910 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911 srb->cmd[4] = 36;
912 srb->datalen = 36;
913 srb->cmdlen = 12;
914 i = ss->transport(srb, ss);
915 USB_STOR_PRINTF("inquiry returns %d\n", i);
916 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000917 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200918 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000919
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100920 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000921 printf("error in inquiry\n");
922 return -1;
923 }
924 return 0;
925}
926
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100927static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000928{
929 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000930
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100931 ptr = (char *)srb->pdata;
932 memset(&srb->cmd[0], 0, 12);
933 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200934 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100935 srb->cmd[4] = 18;
936 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200937 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100938 srb->cmdlen = 12;
939 ss->transport(srb, ss);
940 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
941 srb->sense_buf[2], srb->sense_buf[12],
942 srb->sense_buf[13]);
943 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000944 return 0;
945}
946
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100947static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000948{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200949 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000950
wdenkaffae2b2002-08-17 09:36:01 +0000951 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100952 memset(&srb->cmd[0], 0, 12);
953 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200954 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955 srb->datalen = 0;
956 srb->cmdlen = 12;
957 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000958 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100959 usb_request_sense(srb, ss);
960 wait_ms(100);
961 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000962
wdenkaffae2b2002-08-17 09:36:01 +0000963 return -1;
964}
965
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100966static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000967{
968 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100969 /* XXX retries */
970 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000971 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100972 memset(&srb->cmd[0], 0, 12);
973 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200974 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100975 srb->datalen = 8;
976 srb->cmdlen = 12;
977 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000978 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100979 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000980
wdenkaffae2b2002-08-17 09:36:01 +0000981 return -1;
982}
983
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100984static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
985 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000986{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 memset(&srb->cmd[0], 0, 12);
988 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200989 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100990 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
991 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
992 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
993 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
994 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
995 srb->cmd[8] = (unsigned char) blocks & 0xff;
996 srb->cmdlen = 12;
997 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
998 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +0000999}
1000
Mahavir Jain127e1082009-11-03 12:22:10 +05301001static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1002 unsigned short blocks)
1003{
1004 memset(&srb->cmd[0], 0, 12);
1005 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001006 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301007 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1008 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1009 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1010 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1011 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1012 srb->cmd[8] = (unsigned char) blocks & 0xff;
1013 srb->cmdlen = 12;
1014 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1015 return ss->transport(srb, ss);
1016}
1017
wdenkaffae2b2002-08-17 09:36:01 +00001018
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001019#ifdef CONFIG_USB_BIN_FIXUP
1020/*
1021 * Some USB storage devices queried for SCSI identification data respond with
1022 * binary strings, which if output to the console freeze the terminal. The
1023 * workaround is to modify the vendor and product strings read from such
1024 * device with proper values (as reported by 'usb info').
1025 *
1026 * Vendor and product length limits are taken from the definition of
1027 * block_dev_desc_t in include/part.h.
1028 */
1029static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1030 unsigned char vendor[],
1031 unsigned char product[]) {
1032 const unsigned char max_vendor_len = 40;
1033 const unsigned char max_product_len = 20;
1034 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001035 strncpy((char *)vendor, "SMSC", max_vendor_len);
1036 strncpy((char *)product, "Flash Media Cntrller",
1037 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001038 }
1039}
1040#endif /* CONFIG_USB_BIN_FIXUP */
1041
wdenkaffae2b2002-08-17 09:36:01 +00001042#define USB_MAX_READ_BLK 20
1043
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001044unsigned long usb_stor_read(int device, unsigned long blknr,
1045 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001046{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001047 unsigned long start, blks, buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001048 unsigned short smallblks;
1049 struct usb_device *dev;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001051 ccb *srb = &usb_ccb;
1052
1053 if (blkcnt == 0)
1054 return 0;
1055
1056 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057 /* Setup device */
1058 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1059 dev = NULL;
1060 for (i = 0; i < USB_MAX_DEVICE; i++) {
1061 dev = usb_get_dev_index(i);
1062 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001063 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001065 break;
1066 }
1067
1068 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001069 srb->lun = usb_dev_desc[device].lun;
1070 buf_addr = (unsigned long)buffer;
1071 start = blknr;
1072 blks = blkcnt;
1073 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1074 printf("Device NOT ready\n Request Sense returned %02X %02X"
1075 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1076 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001077 return 0;
1078 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079
1080 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1081 " buffer %lx\n", device, start, blks, buf_addr);
1082
wdenkaffae2b2002-08-17 09:36:01 +00001083 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001084 /* XXX need some comment here */
1085 retry = 2;
1086 srb->pdata = (unsigned char *)buf_addr;
1087 if (blks > USB_MAX_READ_BLK)
1088 smallblks = USB_MAX_READ_BLK;
1089 else
1090 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001091retry_it:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092 if (smallblks == USB_MAX_READ_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001093 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001094 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1095 srb->pdata = (unsigned char *)buf_addr;
1096 if (usb_read_10(srb, (struct us_data *)dev->privptr, start,
1097 smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001098 USB_STOR_PRINTF("Read ERROR\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001099 usb_request_sense(srb, (struct us_data *)dev->privptr);
1100 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001101 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001102 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001103 break;
1104 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001105 start += smallblks;
1106 blks -= smallblks;
1107 buf_addr += srb->datalen;
1108 } while (blks != 0);
1109
1110 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1111 start, smallblks, buf_addr);
1112
wdenkaffae2b2002-08-17 09:36:01 +00001113 usb_disable_asynch(0); /* asynch transfer allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001114 if (blkcnt >= USB_MAX_READ_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001115 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001116 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001117}
1118
Mahavir Jain127e1082009-11-03 12:22:10 +05301119#define USB_MAX_WRITE_BLK 20
1120
1121unsigned 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;
1127 int retry, i;
1128 ccb *srb = &usb_ccb;
1129
1130 if (blkcnt == 0)
1131 return 0;
1132
1133 device &= 0xff;
1134 /* Setup device */
1135 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1136 dev = NULL;
1137 for (i = 0; i < USB_MAX_DEVICE; i++) {
1138 dev = usb_get_dev_index(i);
1139 if (dev == NULL)
1140 return 0;
1141 if (dev->devnum == usb_dev_desc[device].target)
1142 break;
1143 }
1144
1145 usb_disable_asynch(1); /* asynch transfer not allowed */
1146
1147 srb->lun = usb_dev_desc[device].lun;
1148 buf_addr = (unsigned long)buffer;
1149 start = blknr;
1150 blks = blkcnt;
1151 if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
1152 printf("Device NOT ready\n Request Sense returned %02X %02X"
1153 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1154 srb->sense_buf[13]);
1155 return 0;
1156 }
1157
1158 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1159 " buffer %lx\n", device, start, blks, buf_addr);
1160
1161 do {
1162 /* If write fails retry for max retry count else
1163 * return with number of blocks written successfully.
1164 */
1165 retry = 2;
1166 srb->pdata = (unsigned char *)buf_addr;
1167 if (blks > USB_MAX_WRITE_BLK)
1168 smallblks = USB_MAX_WRITE_BLK;
1169 else
1170 smallblks = (unsigned short) blks;
1171retry_it:
1172 if (smallblks == USB_MAX_WRITE_BLK)
1173 usb_show_progress();
1174 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1175 srb->pdata = (unsigned char *)buf_addr;
1176 if (usb_write_10(srb, (struct us_data *)dev->privptr, start,
1177 smallblks)) {
1178 USB_STOR_PRINTF("Write ERROR\n");
1179 usb_request_sense(srb, (struct us_data *)dev->privptr);
1180 if (retry--)
1181 goto retry_it;
1182 blkcnt -= blks;
1183 break;
1184 }
1185 start += smallblks;
1186 blks -= smallblks;
1187 buf_addr += srb->datalen;
1188 } while (blks != 0);
1189
1190 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1191 start, smallblks, buf_addr);
1192
1193 usb_disable_asynch(0); /* asynch transfer allowed */
1194 if (blkcnt >= USB_MAX_WRITE_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001195 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301196 return blkcnt;
1197
1198}
wdenkaffae2b2002-08-17 09:36:01 +00001199
1200/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001201int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1202 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001203{
Tom Rix8f8bd562009-10-31 12:37:38 -05001204 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001205 int i;
1206 unsigned int flags = 0;
1207
1208 int protocol = 0;
1209 int subclass = 0;
1210
wdenkaffae2b2002-08-17 09:36:01 +00001211 /* let's examine the device now */
1212 iface = &dev->config.if_desc[ifnum];
1213
1214#if 0
1215 /* this is the place to patch some storage devices */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001216 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1217 dev->descriptor.idProduct);
1218
1219 if ((dev->descriptor.idVendor) == 0x066b &&
1220 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001221 USB_STOR_PRINTF("patched for E-USB\n");
1222 protocol = US_PR_CB;
1223 subclass = US_SC_UFI; /* an assumption */
1224 }
1225#endif
1226
1227 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001228 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1229 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1230 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001231 /* if it's not a mass storage, we go no further */
1232 return 0;
1233 }
1234
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001235 memset(ss, 0, sizeof(struct us_data));
1236
wdenkaffae2b2002-08-17 09:36:01 +00001237 /* At this point, we know we've got a live one */
1238 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1239
1240 /* Initialize the us_data structure with some useful info */
1241 ss->flags = flags;
1242 ss->ifnum = ifnum;
1243 ss->pusb_dev = dev;
1244 ss->attention_done = 0;
1245
1246 /* If the device has subclass and protocol, then use that. Otherwise,
1247 * take data from the specific interface.
1248 */
1249 if (subclass) {
1250 ss->subclass = subclass;
1251 ss->protocol = protocol;
1252 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001253 ss->subclass = iface->desc.bInterfaceSubClass;
1254 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001255 }
1256
1257 /* set the handler pointers based on the protocol */
1258 USB_STOR_PRINTF("Transport: ");
1259 switch (ss->protocol) {
1260 case US_PR_CB:
1261 USB_STOR_PRINTF("Control/Bulk\n");
1262 ss->transport = usb_stor_CB_transport;
1263 ss->transport_reset = usb_stor_CB_reset;
1264 break;
1265
1266 case US_PR_CBI:
1267 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1268 ss->transport = usb_stor_CB_transport;
1269 ss->transport_reset = usb_stor_CB_reset;
1270 break;
wdenk149dded2003-09-10 18:20:28 +00001271 case US_PR_BULK:
1272 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1273 ss->transport = usb_stor_BBB_transport;
1274 ss->transport_reset = usb_stor_BBB_reset;
1275 break;
wdenkaffae2b2002-08-17 09:36:01 +00001276 default:
wdenk80885a92004-02-26 23:46:20 +00001277 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001278 return 0;
1279 break;
1280 }
1281
1282 /*
1283 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1284 * An optional interrupt is OK (necessary for CBI protocol).
1285 * We will ignore any others.
1286 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001287 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001288 /* is it an BULK endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001289 if ((iface->ep_desc[i].bmAttributes &
1290 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001291 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1292 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1293 USB_ENDPOINT_NUMBER_MASK;
1294 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001295 ss->ep_out =
1296 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001297 USB_ENDPOINT_NUMBER_MASK;
1298 }
1299
1300 /* is it an interrupt endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001301 if ((iface->ep_desc[i].bmAttributes &
1302 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001303 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1304 USB_ENDPOINT_NUMBER_MASK;
1305 ss->irqinterval = iface->ep_desc[i].bInterval;
1306 }
1307 }
1308 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1309 ss->ep_in, ss->ep_out, ss->ep_int);
1310
1311 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001312 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001313 !ss->ep_in || !ss->ep_out ||
1314 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1315 USB_STOR_PRINTF("Problems with device\n");
1316 return 0;
1317 }
1318 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001319 /* We only handle certain protocols. Currently, these are
1320 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001321 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001322 */
wdenk80885a92004-02-26 23:46:20 +00001323 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1324 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001325 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001326 return 0;
1327 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001328 if (ss->ep_int) {
1329 /* we had found an interrupt endpoint, prepare irq pipe
1330 * set up the IRQ pipe and handler
1331 */
wdenkaffae2b2002-08-17 09:36:01 +00001332 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1333 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1334 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001335 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001336 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001337 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001338 return 1;
1339}
1340
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001341int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1342 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001343{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001344 unsigned char perq, modi;
wdenkaffae2b2002-08-17 09:36:01 +00001345 unsigned long cap[2];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001346 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001347 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001348
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001349 pccb->pdata = usb_stor_buf;
1350
1351 dev_desc->target = dev->devnum;
1352 pccb->lun = dev_desc->lun;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001353 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001354
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001355 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001356 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001357
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001358 perq = usb_stor_buf[0];
1359 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001360
1361 if ((perq & 0x1f) == 0x1f) {
1362 /* skip unknown devices */
1363 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001364 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001365 if ((modi&0x80) == 0x80) {
1366 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001367 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001368 }
1369 memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
1370 memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
1371 memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001372 dev_desc->vendor[8] = 0;
1373 dev_desc->product[16] = 0;
1374 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001375#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001376 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1377 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001378#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001379 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1380 usb_stor_buf[3]);
1381 if (usb_test_unit_ready(pccb, ss)) {
1382 printf("Device NOT ready\n"
1383 " Request Sense returned %02X %02X %02X\n",
1384 pccb->sense_buf[2], pccb->sense_buf[12],
1385 pccb->sense_buf[13]);
1386 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001387 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001388 return 1;
1389 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001390 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001391 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001392 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001393 memset(pccb->pdata, 0, 8);
1394 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001395 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001396 cap[0] = 2880;
1397 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001398 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001399 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1400 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001401#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001402 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1403 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001404#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001405 cap[0] = cpu_to_be32(cap[0]);
1406 cap[1] = cpu_to_be32(cap[1]);
1407
wdenk149dded2003-09-10 18:20:28 +00001408 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001409 cap[0] += 1;
1410 capacity = &cap[0];
1411 blksz = &cap[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001412 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1413 *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001414 dev_desc->lba = *capacity;
1415 dev_desc->blksz = *blksz;
1416 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001417 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1418 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001419
1420 init_part(dev_desc);
1421
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001422 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001423 return 1;
1424}