blob: bdc306f587fd9b73b60220d2b49e1151bbf9b4bd [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
Wolfgang Denk460c3222005-08-04 01:14:12 +02002 * Most of this source has been derived from the Linux USB
3 * project:
4 * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
5 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
6 * (c) 1999 Michael Gee (michael@linuxspecific.com)
7 * (c) 2000 Yggdrasil Computing, Inc.
8 *
9 *
10 * Adapted for U-Boot:
11 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
wdenkaffae2b2002-08-17 09:36:01 +000012 *
wdenk149dded2003-09-10 18:20:28 +000013 * For BBB support (C) Copyright 2003
Detlev Zundel792a09e2009-05-13 10:54:10 +020014 * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
wdenk149dded2003-09-10 18:20:28 +000015 *
Wolfgang Denk460c3222005-08-04 01:14:12 +020016 * BBB support based on /sys/dev/usb/umass.c from
wdenk149dded2003-09-10 18:20:28 +000017 * FreeBSD.
wdenkaffae2b2002-08-17 09:36:01 +000018 *
19 * See file CREDITS for list of people who contributed to this
20 * project.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; either version 2 of
25 * the License, or (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wdenk80885a92004-02-26 23:46:20 +000029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenkaffae2b2002-08-17 09:36:01 +000030 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35 * MA 02111-1307 USA
36 *
37 */
38
39/* Note:
40 * Currently only the CBI transport protocoll has been implemented, and it
41 * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
42 * transport protocoll may work as well.
43 */
wdenk149dded2003-09-10 18:20:28 +000044/*
45 * New Note:
46 * Support for USB Mass Storage Devices (BBB) has been added. It has
47 * only been tested with USB memory sticks.
wdenk149dded2003-09-10 18:20:28 +000048 */
wdenkaffae2b2002-08-17 09:36:01 +000049
50
wdenkaffae2b2002-08-17 09:36:01 +000051#include <common.h>
52#include <command.h>
Christian Eggersc9182612008-05-21 22:12:00 +020053#include <asm/byteorder.h>
wdenkaffae2b2002-08-17 09:36:01 +000054#include <asm/processor.h>
55
Grant Likely735dd972007-02-20 09:04:34 +010056#include <part.h>
wdenkaffae2b2002-08-17 09:36:01 +000057#include <usb.h>
58
wdenk80885a92004-02-26 23:46:20 +000059#undef BBB_COMDAT_TRACE
60#undef BBB_XPORT_TRACE
wdenkaffae2b2002-08-17 09:36:01 +000061
62#ifdef USB_STOR_DEBUG
Marek Vasut86bd3ff2011-10-25 11:39:16 +020063#define USB_BLK_DEBUG 1
wdenkaffae2b2002-08-17 09:36:01 +000064#else
Marek Vasut86bd3ff2011-10-25 11:39:16 +020065#define USB_BLK_DEBUG 0
wdenkaffae2b2002-08-17 09:36:01 +000066#endif
67
Marek Vasut86bd3ff2011-10-25 11:39:16 +020068#define USB_STOR_PRINTF(fmt, args...) debug_cond(USB_BLK_DEBUG, fmt, ##args)
69
wdenkaffae2b2002-08-17 09:36:01 +000070#include <scsi.h>
71/* direction table -- this indicates the direction of the data
72 * transfer for each command code -- a 1 indicates input
73 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040074static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000075 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
76 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
79};
80#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
81
Puneet Saxenaf5766132012-04-03 14:56:06 +053082static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
wdenkaffae2b2002-08-17 09:36:01 +000083
84/*
85 * CBI style
86 */
87
88#define US_CBI_ADSC 0
89
wdenk149dded2003-09-10 18:20:28 +000090/*
91 * BULK only
92 */
93#define US_BBB_RESET 0xff
94#define US_BBB_GET_MAX_LUN 0xfe
95
96/* Command Block Wrapper */
97typedef struct {
98 __u32 dCBWSignature;
99# define CBWSIGNATURE 0x43425355
100 __u32 dCBWTag;
101 __u32 dCBWDataTransferLength;
102 __u8 bCBWFlags;
103# define CBWFLAGS_OUT 0x00
104# define CBWFLAGS_IN 0x80
105 __u8 bCBWLUN;
106 __u8 bCDBLength;
107# define CBWCDBLENGTH 16
108 __u8 CBWCDB[CBWCDBLENGTH];
109} umass_bbb_cbw_t;
wdenk80885a92004-02-26 23:46:20 +0000110#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100111static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +0000112
113/* Command Status Wrapper */
114typedef struct {
115 __u32 dCSWSignature;
116# define CSWSIGNATURE 0x53425355
117 __u32 dCSWTag;
118 __u32 dCSWDataResidue;
119 __u8 bCSWStatus;
120# define CSWSTATUS_GOOD 0x0
wdenk80885a92004-02-26 23:46:20 +0000121# define CSWSTATUS_FAILED 0x1
wdenk149dded2003-09-10 18:20:28 +0000122# define CSWSTATUS_PHASE 0x2
123} umass_bbb_csw_t;
wdenk80885a92004-02-26 23:46:20 +0000124#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000125
126#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100127static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000128
129static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
130
131struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100132typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
133typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000134
135struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100136 struct usb_device *pusb_dev; /* this usb_device */
137
138 unsigned int flags; /* from filter initially */
139 unsigned char ifnum; /* interface number */
140 unsigned char ep_in; /* in endpoint */
141 unsigned char ep_out; /* out ....... */
142 unsigned char ep_int; /* interrupt . */
143 unsigned char subclass; /* as in overview */
144 unsigned char protocol; /* .............. */
145 unsigned char attention_done; /* force attn on first cmd */
146 unsigned short ip_data; /* interrupt data */
147 int action; /* what to do */
148 int ip_wanted; /* needed */
149 int *irq_handle; /* for USB int requests */
150 unsigned int irqpipe; /* pipe for release_irq */
151 unsigned char irqmaxp; /* max packed for irq Pipe */
152 unsigned char irqinterval; /* Intervall for IRQ Pipe */
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
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000158/*
159 * The U-Boot EHCI driver cannot handle more than 5 page aligned buffers
160 * of 4096 bytes in a transfer without running itself out of qt_buffers
161 */
162#define USB_MAX_XFER_BLK(start, blksz) (((4096 * 5) - (start % 4096)) / blksz)
163
wdenkaffae2b2002-08-17 09:36:01 +0000164static struct us_data usb_stor[USB_MAX_STOR_DEV];
165
166
wdenk80885a92004-02-26 23:46:20 +0000167#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000168#define USB_STOR_TRANSPORT_FAILED -1
169#define USB_STOR_TRANSPORT_ERROR -2
170
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100171int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
172 block_dev_desc_t *dev_desc);
173int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
174 struct us_data *ss);
175unsigned long usb_stor_read(int device, unsigned long blknr,
176 unsigned long blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530177unsigned long usb_stor_write(int device, unsigned long blknr,
178 unsigned long blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000179struct usb_device * usb_get_dev_index(int index);
180void uhci_show_temp_int_td(void);
181
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000182#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000183block_dev_desc_t *usb_stor_get_dev(int index)
184{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200185 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000186}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000187#endif
wdenkaffae2b2002-08-17 09:36:01 +0000188
189void usb_show_progress(void)
190{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200191 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000192}
193
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100194/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200195 * show info on storage devices; 'usb start/init' must be invoked earlier
196 * as we only retrieve structures populated during devices initialization
197 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100198int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200199{
200 int i;
201
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100202 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200203 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100204 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200205 dev_print(&usb_dev_desc[i]);
206 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100207 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100208 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700209
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100210 printf("No storage devices, perhaps not 'usb start'ed..?\n");
211 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200212}
213
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200214static unsigned int usb_get_max_lun(struct us_data *us)
215{
216 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530217 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200218 len = usb_control_msg(us->pusb_dev,
219 usb_rcvctrlpipe(us->pusb_dev, 0),
220 US_BBB_GET_MAX_LUN,
221 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
222 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530223 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200224 USB_CNTL_TIMEOUT * 5);
225 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
Puneet Saxenaf5766132012-04-03 14:56:06 +0530226 len, (int) *result);
227 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200228}
229
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100230/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200231 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000232 * to the user if mode = 1
233 * returns current device or -1 if no
234 */
235int usb_stor_scan(int mode)
236{
237 unsigned char i;
238 struct usb_device *dev;
239
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100240 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200241 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100242
wdenkaffae2b2002-08-17 09:36:01 +0000243 usb_disable_asynch(1); /* asynch transfer not allowed */
244
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100245 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
246 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100247 usb_dev_desc[i].if_type = IF_TYPE_USB;
248 usb_dev_desc[i].dev = i;
249 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200250 usb_dev_desc[i].target = 0xff;
251 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100252 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530253 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000254 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200255
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100256 usb_max_devs = 0;
257 for (i = 0; i < USB_MAX_DEVICE; i++) {
258 dev = usb_get_dev_index(i); /* get device */
259 USB_STOR_PRINTF("i=%d\n", i);
260 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100261 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100262
263 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200264 /* OK, it's a storage device. Iterate over its LUNs
265 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100266 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200267 int lun, max_lun, start = usb_max_devs;
268
269 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
270 for (lun = 0;
271 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
272 lun++) {
273 usb_dev_desc[usb_max_devs].lun = lun;
274 if (usb_stor_get_info(dev, &usb_stor[start],
275 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000276 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100277 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200278 }
279 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100280 /* if storage device */
281 if (usb_max_devs == USB_MAX_STOR_DEV) {
282 printf("max USB Storage Device reached: %d stopping\n",
283 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000284 break;
285 }
286 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200287
wdenkaffae2b2002-08-17 09:36:01 +0000288 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200289 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100290 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000291 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100292 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000293}
294
295static int usb_stor_irq(struct usb_device *dev)
296{
297 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100298 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000299
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100300 if (us->ip_wanted)
301 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000302 return 0;
303}
304
305
306#ifdef USB_STOR_DEBUG
307
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100308static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000309{
310 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100311 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
312 for (i = 0; i < 12; i++)
313 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000314 printf("\n");
315}
316
317static void display_int_status(unsigned long tmp)
318{
319 printf("Status: %s %s %s %s %s %s %s\n",
320 (tmp & USB_ST_ACTIVE) ? "Active" : "",
321 (tmp & USB_ST_STALLED) ? "Stalled" : "",
322 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
323 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
324 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
325 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
326 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
327}
328#endif
329/***********************************************************************
330 * Data transfer routines
331 ***********************************************************************/
332
333static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
334{
335 int max_size;
336 int this_xfer;
337 int result;
338 int partial;
339 int maxtry;
340 int stat;
341
342 /* determine the maximum packet size for these transfers */
343 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
344
345 /* while we have data left to transfer */
346 while (length) {
347
348 /* calculate how long this will be -- maximum or a remainder */
349 this_xfer = length > max_size ? max_size : length;
350 length -= this_xfer;
351
352 /* setup the retry counter */
353 maxtry = 10;
354
355 /* set up the transfer loop */
356 do {
357 /* transfer the data */
358 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
359 (unsigned int)buf, this_xfer, 11 - maxtry);
360 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100361 this_xfer, &partial,
362 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000363 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
364 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100365 if (us->pusb_dev->status != 0) {
366 /* if we stall, we need to clear it before
367 * we go on
368 */
wdenkaffae2b2002-08-17 09:36:01 +0000369#ifdef USB_STOR_DEBUG
370 display_int_status(us->pusb_dev->status);
371#endif
372 if (us->pusb_dev->status & USB_ST_STALLED) {
373 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
374 stat = us->pusb_dev->status;
375 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100376 us->pusb_dev->status = stat;
377 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200378 USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000379 return 0;
380 }
381 else
382 return result;
383 }
384 if (us->pusb_dev->status & USB_ST_NAK_REC) {
385 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
386 return result;
387 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100388 USB_STOR_PRINTF("bulk transferred with error");
389 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200390 USB_STOR_PRINTF(" %ld, but data ok\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100391 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000392 return 0;
393 }
394 /* if our try counter reaches 0, bail out */
Marek Vasut4b210e82011-10-25 11:39:17 +0200395 USB_STOR_PRINTF(" %ld, data %d\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100396 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000397 if (!maxtry--)
398 return result;
399 }
400 /* update to show what data was transferred */
401 this_xfer -= partial;
402 buf += partial;
403 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100404 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000405 }
406
407 /* if we get here, we're done and successful */
408 return 0;
409}
410
wdenk149dded2003-09-10 18:20:28 +0000411static int usb_stor_BBB_reset(struct us_data *us)
412{
413 int result;
414 unsigned int pipe;
415
416 /*
417 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
418 *
419 * For Reset Recovery the host shall issue in the following order:
420 * a) a Bulk-Only Mass Storage Reset
421 * b) a Clear Feature HALT to the Bulk-In endpoint
422 * c) a Clear Feature HALT to the Bulk-Out endpoint
423 *
424 * This is done in 3 steps.
425 *
426 * If the reset doesn't succeed, the device should be port reset.
427 *
428 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
429 */
430 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100431 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
432 US_BBB_RESET,
433 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
434 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200435
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100436 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000437 USB_STOR_PRINTF("RESET:stall\n");
438 return -1;
439 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200440
wdenk149dded2003-09-10 18:20:28 +0000441 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000442 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200443 USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100444 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000445 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
446 result = usb_clear_halt(us->pusb_dev, pipe);
447 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000448 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200449 USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100450 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000451 /* long wait for reset */
452 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
453 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000454 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200455 USB_STOR_PRINTF("BBB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100456 " clearing OUT endpoint\n", result,
457 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000458 USB_STOR_PRINTF("BBB_reset done\n");
459 return 0;
460}
461
wdenkaffae2b2002-08-17 09:36:01 +0000462/* FIXME: this reset function doesn't really reset the port, and it
463 * should. Actually it should probably do what it's doing here, and
464 * reset the port physically
465 */
466static int usb_stor_CB_reset(struct us_data *us)
467{
468 unsigned char cmd[12];
469 int result;
470
471 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100472 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000473 cmd[0] = SCSI_SEND_DIAG;
474 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100475 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
476 US_CBI_ADSC,
477 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
478 0, us->ifnum, cmd, sizeof(cmd),
479 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000480
481 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000482 mdelay(1500);
Marek Vasut4b210e82011-10-25 11:39:17 +0200483 USB_STOR_PRINTF("CB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100484 " clearing endpoint halt\n", result,
485 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000486 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
487 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
488
489 USB_STOR_PRINTF("CB_reset done\n");
490 return 0;
491}
492
wdenk149dded2003-09-10 18:20:28 +0000493/*
494 * Set up the command for a BBB device. Note that the actual SCSI
495 * command is copied into cbw.CBWCDB.
496 */
497int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
498{
499 int result;
500 int actlen;
501 int dir_in;
502 unsigned int pipe;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530503 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000504
505 dir_in = US_DIRECTION(srb->cmd[0]);
506
507#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
509 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
510 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000511 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100512 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000513 printf("cmd[%d] %#x ", result, srb->cmd[result]);
514 printf("\n");
515 }
516#endif
517 /* sanity checks */
518 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
519 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
520 return -1;
521 }
522
523 /* always OUT to the ep */
524 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
525
Puneet Saxenaf5766132012-04-03 14:56:06 +0530526 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
527 cbw->dCBWTag = cpu_to_le32(CBWTag++);
528 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
529 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
530 cbw->bCBWLUN = srb->lun;
531 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000532 /* copy the command data into the CBW command data buffer */
533 /* DST SRC LEN!!! */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530534 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
535 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100536 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000537 if (result < 0)
538 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
539 return result;
540}
541
wdenkaffae2b2002-08-17 09:36:01 +0000542/* FIXME: we also need a CBI_command which sets up the completion
543 * interrupt, and waits for it
544 */
545int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
546{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200547 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100548 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000549 unsigned int pipe;
550 unsigned long status;
551
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100552 retry = 5;
553 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000554
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100555 if (dir_in)
556 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
557 else
558 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
559
560 while (retry--) {
561 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000562#ifdef USB_STOR_DEBUG
563 usb_show_srb(srb);
564#endif
565 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100566 result = usb_control_msg(us->pusb_dev,
567 usb_sndctrlpipe(us->pusb_dev , 0),
568 US_CBI_ADSC,
569 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000570 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100571 srb->cmd, srb->cmdlen,
572 USB_CNTL_TIMEOUT * 5);
573 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
Marek Vasut4b210e82011-10-25 11:39:17 +0200574 " status %lX\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000575 /* check the return code for the command */
576 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100577 if (us->pusb_dev->status & USB_ST_STALLED) {
578 status = us->pusb_dev->status;
579 USB_STOR_PRINTF(" stall during command found,"
580 " clear pipe\n");
581 usb_clear_halt(us->pusb_dev,
582 usb_sndctrlpipe(us->pusb_dev, 0));
583 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000584 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100585 USB_STOR_PRINTF(" error during command %02X"
Marek Vasut4b210e82011-10-25 11:39:17 +0200586 " Stat = %lX\n", srb->cmd[0],
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100587 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000588 return result;
589 }
590 /* transfer the data payload for this command, if one exists*/
591
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100592 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
593 " direction is %s to go 0x%lx\n", result,
594 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000595 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100596 result = us_one_transfer(us, pipe, (char *)srb->pdata,
597 srb->datalen);
598 USB_STOR_PRINTF("CBI attempted to transfer data,"
599 " result is %d status %lX, len %d\n",
600 result, us->pusb_dev->status,
601 us->pusb_dev->act_len);
602 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000603 break;
604 } /* if (srb->datalen) */
605 else
606 break;
607 }
608 /* return result */
609
610 return result;
611}
612
613
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100614int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000615{
616 int timeout;
617
wdenk80885a92004-02-26 23:46:20 +0000618 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100619 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000620 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
621 timeout = 1000;
622 while (timeout--) {
623 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000624 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000625 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000626 }
627 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100628 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000629 us->ip_wanted = 0;
630 return USB_STOR_TRANSPORT_ERROR;
631 }
wdenk80885a92004-02-26 23:46:20 +0000632 USB_STOR_PRINTF
633 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
634 us->ip_data, us->pusb_dev->irq_act_len,
635 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000636 /* UFI gives us ASC and ASCQ, like a request sense */
637 if (us->subclass == US_SC_UFI) {
638 if (srb->cmd[0] == SCSI_REQ_SENSE ||
639 srb->cmd[0] == SCSI_INQUIRY)
640 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000641 else if (us->ip_data)
642 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000643 else
wdenk80885a92004-02-26 23:46:20 +0000644 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000645 }
646 /* otherwise, we interpret the data normally */
647 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000648 case 0x0001:
649 return USB_STOR_TRANSPORT_GOOD;
650 case 0x0002:
651 return USB_STOR_TRANSPORT_FAILED;
652 default:
653 return USB_STOR_TRANSPORT_ERROR;
654 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000655 return USB_STOR_TRANSPORT_ERROR;
656}
657
658#define USB_TRANSPORT_UNKNOWN_RETRY 5
659#define USB_TRANSPORT_NOT_READY_RETRY 10
660
wdenk149dded2003-09-10 18:20:28 +0000661/* clear a stall on an endpoint - special for BBB devices */
662int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
663{
664 int result;
665
666 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100667 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000668 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100669 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000670 return result;
671}
672
673int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
674{
675 int result, retry;
676 int dir_in;
677 int actlen, data_actlen;
678 unsigned int pipe, pipein, pipeout;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530679 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000680#ifdef BBB_XPORT_TRACE
681 unsigned char *ptr;
682 int index;
683#endif
684
685 dir_in = US_DIRECTION(srb->cmd[0]);
686
687 /* COMMAND phase */
688 USB_STOR_PRINTF("COMMAND phase\n");
689 result = usb_stor_BBB_comdat(srb, us);
690 if (result < 0) {
691 USB_STOR_PRINTF("failed to send CBW status %ld\n",
692 us->pusb_dev->status);
693 usb_stor_BBB_reset(us);
694 return USB_STOR_TRANSPORT_FAILED;
695 }
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000696 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000697 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
698 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
699 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000700 data_actlen = 0;
701 /* no data, go immediately to the STATUS phase */
702 if (srb->datalen == 0)
703 goto st;
wdenk80885a92004-02-26 23:46:20 +0000704 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000705 if (dir_in)
706 pipe = pipein;
707 else
708 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100709 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
710 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000711 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100712 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000713 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000714 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100715 result = usb_stor_BBB_clear_endpt_stall(us,
716 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000717 if (result >= 0)
718 /* continue on to STATUS phase */
719 goto st;
720 }
721 if (result < 0) {
722 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
723 us->pusb_dev->status);
724 usb_stor_BBB_reset(us);
725 return USB_STOR_TRANSPORT_FAILED;
726 }
727#ifdef BBB_XPORT_TRACE
728 for (index = 0; index < data_actlen; index++)
729 printf("pdata[%d] %#x ", index, srb->pdata[index]);
730 printf("\n");
731#endif
732 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100733st:
wdenk149dded2003-09-10 18:20:28 +0000734 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100735again:
wdenk149dded2003-09-10 18:20:28 +0000736 USB_STOR_PRINTF("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530737 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200738 &actlen, USB_CNTL_TIMEOUT*5);
739
wdenk149dded2003-09-10 18:20:28 +0000740 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100741 if ((result < 0) && (retry < 1) &&
742 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000743 USB_STOR_PRINTF("STATUS:stall\n");
744 /* clear the STALL on the endpoint */
745 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
746 if (result >= 0 && (retry++ < 1))
747 /* do a retry */
748 goto again;
749 }
750 if (result < 0) {
751 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
752 us->pusb_dev->status);
753 usb_stor_BBB_reset(us);
754 return USB_STOR_TRANSPORT_FAILED;
755 }
756#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530757 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000758 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
759 printf("ptr[%d] %#x ", index, ptr[index]);
760 printf("\n");
761#endif
762 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530763 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000764 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
765 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530766 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000767 USB_STOR_PRINTF("!CSWSIGNATURE\n");
768 usb_stor_BBB_reset(us);
769 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530770 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000771 USB_STOR_PRINTF("!Tag\n");
772 usb_stor_BBB_reset(us);
773 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530774 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
wdenk149dded2003-09-10 18:20:28 +0000775 USB_STOR_PRINTF(">PHASE\n");
776 usb_stor_BBB_reset(us);
777 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530778 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
wdenk149dded2003-09-10 18:20:28 +0000779 USB_STOR_PRINTF("=PHASE\n");
780 usb_stor_BBB_reset(us);
781 return USB_STOR_TRANSPORT_FAILED;
782 } else if (data_actlen > srb->datalen) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200783 USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
wdenk149dded2003-09-10 18:20:28 +0000784 data_actlen, srb->datalen);
785 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530786 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
wdenk149dded2003-09-10 18:20:28 +0000787 USB_STOR_PRINTF("FAILED\n");
788 return USB_STOR_TRANSPORT_FAILED;
789 }
790
791 return result;
792}
793
wdenkaffae2b2002-08-17 09:36:01 +0000794int usb_stor_CB_transport(ccb *srb, struct us_data *us)
795{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100796 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000797 ccb *psrb;
798 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100799 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000800
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200801 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100802 status = USB_STOR_TRANSPORT_GOOD;
803 retry = 0;
804 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000805 /* issue the command */
806do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100807 result = usb_stor_CB_comdat(srb, us);
Marek Vasut4b210e82011-10-25 11:39:17 +0200808 USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100809 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000810 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100811 if (us->protocol == US_PR_CBI) {
812 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000813 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100814 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000815 USB_STOR_PRINTF(" USB CBI Command Error\n");
816 return status;
817 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100818 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
819 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
820 if (!us->ip_data) {
821 /* if the status is good, report it */
822 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000823 USB_STOR_PRINTF(" USB CBI Command Good\n");
824 return status;
825 }
826 }
827 }
828 /* do we have to issue an auto request? */
829 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100830 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200831 USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000832 us->transport_reset(us);
833 return USB_STOR_TRANSPORT_ERROR;
834 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100835 if ((us->protocol == US_PR_CBI) &&
836 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
837 (srb->cmd[0] == SCSI_INQUIRY))) {
838 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000839 USB_STOR_PRINTF("No auto request and good\n");
840 return USB_STOR_TRANSPORT_GOOD;
841 }
842 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100843 memset(&psrb->cmd[0], 0, 12);
844 psrb->cmd[0] = SCSI_REQ_SENSE;
845 psrb->cmd[1] = srb->lun << 5;
846 psrb->cmd[4] = 18;
847 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200848 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100849 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000850 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100851 result = usb_stor_CB_comdat(psrb, us);
852 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000853 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100854 if (us->protocol == US_PR_CBI)
855 status = usb_stor_CBI_get_status(psrb, us);
856
857 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200858 USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100859 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000860 return USB_STOR_TRANSPORT_ERROR;
861 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100862 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
863 srb->sense_buf[0], srb->sense_buf[2],
864 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000865 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 if ((srb->sense_buf[2] == 0) &&
867 (srb->sense_buf[12] == 0) &&
868 (srb->sense_buf[13] == 0)) {
869 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000870 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100871 }
872
wdenkaffae2b2002-08-17 09:36:01 +0000873 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100874 switch (srb->sense_buf[2]) {
875 case 0x01:
876 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000877 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000878 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100879 case 0x02:
880 /* Not Ready */
881 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
882 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
883 " 0x%02X (NOT READY)\n", srb->cmd[0],
884 srb->sense_buf[0], srb->sense_buf[2],
885 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000886 return USB_STOR_TRANSPORT_FAILED;
887 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000888 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000889 goto do_retry;
890 }
891 break;
892 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100893 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
894 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
895 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
896 srb->sense_buf[2], srb->sense_buf[12],
897 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000898 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100899 } else
wdenk149dded2003-09-10 18:20:28 +0000900 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000901 break;
wdenkaffae2b2002-08-17 09:36:01 +0000902 }
903 return USB_STOR_TRANSPORT_FAILED;
904}
905
906
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100907static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000908{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100909 int retry, i;
910 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000911 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100912 memset(&srb->cmd[0], 0, 12);
913 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200914 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100915 srb->cmd[4] = 36;
916 srb->datalen = 36;
917 srb->cmdlen = 12;
918 i = ss->transport(srb, ss);
919 USB_STOR_PRINTF("inquiry returns %d\n", i);
920 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000921 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200922 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000923
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100924 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000925 printf("error in inquiry\n");
926 return -1;
927 }
928 return 0;
929}
930
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100931static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000932{
933 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000934
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100935 ptr = (char *)srb->pdata;
936 memset(&srb->cmd[0], 0, 12);
937 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200938 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100939 srb->cmd[4] = 18;
940 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200941 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100942 srb->cmdlen = 12;
943 ss->transport(srb, ss);
944 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
945 srb->sense_buf[2], srb->sense_buf[12],
946 srb->sense_buf[13]);
947 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000948 return 0;
949}
950
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100951static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000952{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200953 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000954
wdenkaffae2b2002-08-17 09:36:01 +0000955 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100956 memset(&srb->cmd[0], 0, 12);
957 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200958 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100959 srb->datalen = 0;
960 srb->cmdlen = 12;
961 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000962 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100963 usb_request_sense(srb, ss);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000964 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100965 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000966
wdenkaffae2b2002-08-17 09:36:01 +0000967 return -1;
968}
969
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100970static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000971{
972 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100973 /* XXX retries */
974 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000975 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 memset(&srb->cmd[0], 0, 12);
977 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200978 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100979 srb->datalen = 8;
980 srb->cmdlen = 12;
981 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000982 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100983 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000984
wdenkaffae2b2002-08-17 09:36:01 +0000985 return -1;
986}
987
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100988static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
989 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000990{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100991 memset(&srb->cmd[0], 0, 12);
992 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200993 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100994 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
995 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
996 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
997 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
998 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
999 srb->cmd[8] = (unsigned char) blocks & 0xff;
1000 srb->cmdlen = 12;
1001 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
1002 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001003}
1004
Mahavir Jain127e1082009-11-03 12:22:10 +05301005static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1006 unsigned short blocks)
1007{
1008 memset(&srb->cmd[0], 0, 12);
1009 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001010 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301011 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1012 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1013 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1014 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1015 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1016 srb->cmd[8] = (unsigned char) blocks & 0xff;
1017 srb->cmdlen = 12;
1018 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1019 return ss->transport(srb, ss);
1020}
1021
wdenkaffae2b2002-08-17 09:36:01 +00001022
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001023#ifdef CONFIG_USB_BIN_FIXUP
1024/*
1025 * Some USB storage devices queried for SCSI identification data respond with
1026 * binary strings, which if output to the console freeze the terminal. The
1027 * workaround is to modify the vendor and product strings read from such
1028 * device with proper values (as reported by 'usb info').
1029 *
1030 * Vendor and product length limits are taken from the definition of
1031 * block_dev_desc_t in include/part.h.
1032 */
1033static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1034 unsigned char vendor[],
1035 unsigned char product[]) {
1036 const unsigned char max_vendor_len = 40;
1037 const unsigned char max_product_len = 20;
1038 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001039 strncpy((char *)vendor, "SMSC", max_vendor_len);
1040 strncpy((char *)product, "Flash Media Cntrller",
1041 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001042 }
1043}
1044#endif /* CONFIG_USB_BIN_FIXUP */
1045
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001046unsigned long usb_stor_read(int device, unsigned long blknr,
1047 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001048{
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001049 unsigned long start, blks, buf_addr, max_xfer_blk;
wdenkaffae2b2002-08-17 09:36:01 +00001050 unsigned short smallblks;
1051 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001052 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001053 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001054 ccb *srb = &usb_ccb;
1055
1056 if (blkcnt == 0)
1057 return 0;
1058
1059 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001060 /* Setup device */
1061 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1062 dev = NULL;
1063 for (i = 0; i < USB_MAX_DEVICE; i++) {
1064 dev = usb_get_dev_index(i);
1065 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001066 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001067 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001068 break;
1069 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001070 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001071
1072 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001073 srb->lun = usb_dev_desc[device].lun;
1074 buf_addr = (unsigned long)buffer;
1075 start = blknr;
1076 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001077 if (usb_test_unit_ready(srb, ss)) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001078 printf("Device NOT ready\n Request Sense returned %02X %02X"
1079 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1080 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001081 return 0;
1082 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001083
1084 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1085 " buffer %lx\n", device, start, blks, buf_addr);
1086
wdenkaffae2b2002-08-17 09:36:01 +00001087 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001088 /* XXX need some comment here */
1089 retry = 2;
1090 srb->pdata = (unsigned char *)buf_addr;
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001091 max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
1092 usb_dev_desc[device].blksz);
1093 if (blks > max_xfer_blk)
1094 smallblks = (unsigned short) max_xfer_blk;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001095 else
1096 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001097retry_it:
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001098 if (smallblks == max_xfer_blk)
wdenkaffae2b2002-08-17 09:36:01 +00001099 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001100 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1101 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001102 if (usb_read_10(srb, ss, start, smallblks)) {
wdenkaffae2b2002-08-17 09:36:01 +00001103 USB_STOR_PRINTF("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001104 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001105 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001106 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001107 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001108 break;
1109 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001110 start += smallblks;
1111 blks -= smallblks;
1112 buf_addr += srb->datalen;
1113 } while (blks != 0);
1114
1115 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1116 start, smallblks, buf_addr);
1117
wdenkaffae2b2002-08-17 09:36:01 +00001118 usb_disable_asynch(0); /* asynch transfer allowed */
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001119 if (blkcnt >= max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001120 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001121 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001122}
1123
Mahavir Jain127e1082009-11-03 12:22:10 +05301124unsigned long usb_stor_write(int device, unsigned long blknr,
1125 unsigned long blkcnt, const void *buffer)
1126{
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001127 unsigned long start, blks, buf_addr, max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301128 unsigned short smallblks;
1129 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001130 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301131 int retry, i;
1132 ccb *srb = &usb_ccb;
1133
1134 if (blkcnt == 0)
1135 return 0;
1136
1137 device &= 0xff;
1138 /* Setup device */
1139 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1140 dev = NULL;
1141 for (i = 0; i < USB_MAX_DEVICE; i++) {
1142 dev = usb_get_dev_index(i);
1143 if (dev == NULL)
1144 return 0;
1145 if (dev->devnum == usb_dev_desc[device].target)
1146 break;
1147 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001148 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301149
1150 usb_disable_asynch(1); /* asynch transfer not allowed */
1151
1152 srb->lun = usb_dev_desc[device].lun;
1153 buf_addr = (unsigned long)buffer;
1154 start = blknr;
1155 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001156 if (usb_test_unit_ready(srb, ss)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301157 printf("Device NOT ready\n Request Sense returned %02X %02X"
1158 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1159 srb->sense_buf[13]);
1160 return 0;
1161 }
1162
1163 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1164 " buffer %lx\n", device, start, blks, buf_addr);
1165
1166 do {
1167 /* If write fails retry for max retry count else
1168 * return with number of blocks written successfully.
1169 */
1170 retry = 2;
1171 srb->pdata = (unsigned char *)buf_addr;
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001172 max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
1173 usb_dev_desc[device].blksz);
1174 if (blks > max_xfer_blk)
1175 smallblks = (unsigned short) max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301176 else
1177 smallblks = (unsigned short) blks;
1178retry_it:
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001179 if (smallblks == max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301180 usb_show_progress();
1181 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1182 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001183 if (usb_write_10(srb, ss, start, smallblks)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301184 USB_STOR_PRINTF("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001185 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301186 if (retry--)
1187 goto retry_it;
1188 blkcnt -= blks;
1189 break;
1190 }
1191 start += smallblks;
1192 blks -= smallblks;
1193 buf_addr += srb->datalen;
1194 } while (blks != 0);
1195
1196 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1197 start, smallblks, buf_addr);
1198
1199 usb_disable_asynch(0); /* asynch transfer allowed */
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001200 if (blkcnt >= max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001201 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301202 return blkcnt;
1203
1204}
wdenkaffae2b2002-08-17 09:36:01 +00001205
1206/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001207int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1208 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001209{
Tom Rix8f8bd562009-10-31 12:37:38 -05001210 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001211 int i;
1212 unsigned int flags = 0;
1213
1214 int protocol = 0;
1215 int subclass = 0;
1216
wdenkaffae2b2002-08-17 09:36:01 +00001217 /* let's examine the device now */
1218 iface = &dev->config.if_desc[ifnum];
1219
1220#if 0
1221 /* this is the place to patch some storage devices */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001222 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1223 dev->descriptor.idProduct);
1224
1225 if ((dev->descriptor.idVendor) == 0x066b &&
1226 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001227 USB_STOR_PRINTF("patched for E-USB\n");
1228 protocol = US_PR_CB;
1229 subclass = US_SC_UFI; /* an assumption */
1230 }
1231#endif
1232
1233 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001234 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1235 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1236 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001237 /* if it's not a mass storage, we go no further */
1238 return 0;
1239 }
1240
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001241 memset(ss, 0, sizeof(struct us_data));
1242
wdenkaffae2b2002-08-17 09:36:01 +00001243 /* At this point, we know we've got a live one */
1244 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1245
1246 /* Initialize the us_data structure with some useful info */
1247 ss->flags = flags;
1248 ss->ifnum = ifnum;
1249 ss->pusb_dev = dev;
1250 ss->attention_done = 0;
1251
1252 /* If the device has subclass and protocol, then use that. Otherwise,
1253 * take data from the specific interface.
1254 */
1255 if (subclass) {
1256 ss->subclass = subclass;
1257 ss->protocol = protocol;
1258 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001259 ss->subclass = iface->desc.bInterfaceSubClass;
1260 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001261 }
1262
1263 /* set the handler pointers based on the protocol */
1264 USB_STOR_PRINTF("Transport: ");
1265 switch (ss->protocol) {
1266 case US_PR_CB:
1267 USB_STOR_PRINTF("Control/Bulk\n");
1268 ss->transport = usb_stor_CB_transport;
1269 ss->transport_reset = usb_stor_CB_reset;
1270 break;
1271
1272 case US_PR_CBI:
1273 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1274 ss->transport = usb_stor_CB_transport;
1275 ss->transport_reset = usb_stor_CB_reset;
1276 break;
wdenk149dded2003-09-10 18:20:28 +00001277 case US_PR_BULK:
1278 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1279 ss->transport = usb_stor_BBB_transport;
1280 ss->transport_reset = usb_stor_BBB_reset;
1281 break;
wdenkaffae2b2002-08-17 09:36:01 +00001282 default:
wdenk80885a92004-02-26 23:46:20 +00001283 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001284 return 0;
1285 break;
1286 }
1287
1288 /*
1289 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1290 * An optional interrupt is OK (necessary for CBI protocol).
1291 * We will ignore any others.
1292 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001293 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001294 /* is it an BULK endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001295 if ((iface->ep_desc[i].bmAttributes &
1296 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001297 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1298 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1299 USB_ENDPOINT_NUMBER_MASK;
1300 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001301 ss->ep_out =
1302 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001303 USB_ENDPOINT_NUMBER_MASK;
1304 }
1305
1306 /* is it an interrupt endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001307 if ((iface->ep_desc[i].bmAttributes &
1308 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001309 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1310 USB_ENDPOINT_NUMBER_MASK;
1311 ss->irqinterval = iface->ep_desc[i].bInterval;
1312 }
1313 }
1314 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1315 ss->ep_in, ss->ep_out, ss->ep_int);
1316
1317 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001318 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001319 !ss->ep_in || !ss->ep_out ||
1320 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1321 USB_STOR_PRINTF("Problems with device\n");
1322 return 0;
1323 }
1324 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001325 /* We only handle certain protocols. Currently, these are
1326 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001327 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001328 */
wdenk80885a92004-02-26 23:46:20 +00001329 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1330 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001331 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001332 return 0;
1333 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001334 if (ss->ep_int) {
1335 /* we had found an interrupt endpoint, prepare irq pipe
1336 * set up the IRQ pipe and handler
1337 */
wdenkaffae2b2002-08-17 09:36:01 +00001338 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1339 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1340 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001341 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001342 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001343 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001344 return 1;
1345}
1346
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001347int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1348 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001349{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001350 unsigned char perq, modi;
Puneet Saxenaf5766132012-04-03 14:56:06 +05301351 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1352 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001353 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001354 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001355
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001356 pccb->pdata = usb_stor_buf;
1357
1358 dev_desc->target = dev->devnum;
1359 pccb->lun = dev_desc->lun;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001360 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001361
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001362 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001363 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001364
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001365 perq = usb_stor_buf[0];
1366 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001367
1368 if ((perq & 0x1f) == 0x1f) {
1369 /* skip unknown devices */
1370 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001371 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001372 if ((modi&0x80) == 0x80) {
1373 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001374 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001375 }
Puneet Saxenaf5766132012-04-03 14:56:06 +05301376 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1377 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1378 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001379 dev_desc->vendor[8] = 0;
1380 dev_desc->product[16] = 0;
1381 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001382#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001383 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1384 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001385#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001386 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1387 usb_stor_buf[3]);
1388 if (usb_test_unit_ready(pccb, ss)) {
1389 printf("Device NOT ready\n"
1390 " Request Sense returned %02X %02X %02X\n",
1391 pccb->sense_buf[2], pccb->sense_buf[12],
1392 pccb->sense_buf[13]);
1393 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001394 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001395 return 1;
1396 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001397 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001398 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001399 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001400 memset(pccb->pdata, 0, 8);
1401 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001402 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001403 cap[0] = 2880;
1404 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001405 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001406 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1407 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001408#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001409 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1410 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001411#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001412 cap[0] = cpu_to_be32(cap[0]);
1413 cap[1] = cpu_to_be32(cap[1]);
1414
wdenk149dded2003-09-10 18:20:28 +00001415 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001416 cap[0] += 1;
1417 capacity = &cap[0];
1418 blksz = &cap[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001419 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1420 *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001421 dev_desc->lba = *capacity;
1422 dev_desc->blksz = *blksz;
1423 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001424 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1425 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001426
1427 init_part(dev_desc);
1428
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001429 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001430 return 1;
1431}