blob: 457970f770ce774b6c3e5f461f3216b411258951 [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
wdenkaffae2b2002-08-17 09:36:01 +000062#include <scsi.h>
63/* direction table -- this indicates the direction of the data
64 * transfer for each command code -- a 1 indicates input
65 */
Mike Frysinger2ff122852010-10-20 07:16:04 -040066static const unsigned char us_direction[256/8] = {
wdenkaffae2b2002-08-17 09:36:01 +000067 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
68 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
71};
72#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
73
Puneet Saxenaf5766132012-04-03 14:56:06 +053074static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
wdenkaffae2b2002-08-17 09:36:01 +000075
76/*
77 * CBI style
78 */
79
80#define US_CBI_ADSC 0
81
wdenk149dded2003-09-10 18:20:28 +000082/*
83 * BULK only
84 */
85#define US_BBB_RESET 0xff
86#define US_BBB_GET_MAX_LUN 0xfe
87
88/* Command Block Wrapper */
89typedef struct {
90 __u32 dCBWSignature;
91# define CBWSIGNATURE 0x43425355
92 __u32 dCBWTag;
93 __u32 dCBWDataTransferLength;
94 __u8 bCBWFlags;
95# define CBWFLAGS_OUT 0x00
96# define CBWFLAGS_IN 0x80
97 __u8 bCBWLUN;
98 __u8 bCDBLength;
99# define CBWCDBLENGTH 16
100 __u8 CBWCDB[CBWCDBLENGTH];
101} umass_bbb_cbw_t;
wdenk80885a92004-02-26 23:46:20 +0000102#define UMASS_BBB_CBW_SIZE 31
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100103static __u32 CBWTag;
wdenk149dded2003-09-10 18:20:28 +0000104
105/* Command Status Wrapper */
106typedef struct {
107 __u32 dCSWSignature;
108# define CSWSIGNATURE 0x53425355
109 __u32 dCSWTag;
110 __u32 dCSWDataResidue;
111 __u8 bCSWStatus;
112# define CSWSTATUS_GOOD 0x0
wdenk80885a92004-02-26 23:46:20 +0000113# define CSWSTATUS_FAILED 0x1
wdenk149dded2003-09-10 18:20:28 +0000114# define CSWSTATUS_PHASE 0x2
115} umass_bbb_csw_t;
wdenk80885a92004-02-26 23:46:20 +0000116#define UMASS_BBB_CSW_SIZE 13
wdenkaffae2b2002-08-17 09:36:01 +0000117
118#define USB_MAX_STOR_DEV 5
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100119static int usb_max_devs; /* number of highest available usb device */
wdenkaffae2b2002-08-17 09:36:01 +0000120
121static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
122
123struct us_data;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100124typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
125typedef int (*trans_reset)(struct us_data *data);
wdenkaffae2b2002-08-17 09:36:01 +0000126
127struct us_data {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100128 struct usb_device *pusb_dev; /* this usb_device */
129
130 unsigned int flags; /* from filter initially */
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200131# define USB_READY (1 << 0)
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100132 unsigned char ifnum; /* interface number */
133 unsigned char ep_in; /* in endpoint */
134 unsigned char ep_out; /* out ....... */
135 unsigned char ep_int; /* interrupt . */
136 unsigned char subclass; /* as in overview */
137 unsigned char protocol; /* .............. */
138 unsigned char attention_done; /* force attn on first cmd */
139 unsigned short ip_data; /* interrupt data */
140 int action; /* what to do */
141 int ip_wanted; /* needed */
142 int *irq_handle; /* for USB int requests */
143 unsigned int irqpipe; /* pipe for release_irq */
144 unsigned char irqmaxp; /* max packed for irq Pipe */
145 unsigned char irqinterval; /* Intervall for IRQ Pipe */
146 ccb *srb; /* current srb */
147 trans_reset transport_reset; /* reset routine */
148 trans_cmnd transport; /* transport routine */
wdenkaffae2b2002-08-17 09:36:01 +0000149};
150
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200151#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000152/*
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200153 * The U-Boot EHCI driver can handle any transfer length as long as there is
154 * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
155 * limited to 65535 blocks.
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000156 */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200157#define USB_MAX_XFER_BLK 65535
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200158#else
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +0200159#define USB_MAX_XFER_BLK 20
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200160#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000161
wdenkaffae2b2002-08-17 09:36:01 +0000162static struct us_data usb_stor[USB_MAX_STOR_DEV];
163
164
wdenk80885a92004-02-26 23:46:20 +0000165#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000166#define USB_STOR_TRANSPORT_FAILED -1
167#define USB_STOR_TRANSPORT_ERROR -2
168
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100169int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
170 block_dev_desc_t *dev_desc);
171int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
172 struct us_data *ss);
173unsigned long usb_stor_read(int device, unsigned long blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000174 lbaint_t blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530175unsigned long usb_stor_write(int device, unsigned long blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +0000176 lbaint_t blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000177struct usb_device * usb_get_dev_index(int index);
178void uhci_show_temp_int_td(void);
179
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000180#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000181block_dev_desc_t *usb_stor_get_dev(int index)
182{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200183 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000184}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000185#endif
wdenkaffae2b2002-08-17 09:36:01 +0000186
Kim Phillips199adb62012-10-29 13:34:32 +0000187static void usb_show_progress(void)
wdenkaffae2b2002-08-17 09:36:01 +0000188{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200189 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000190}
191
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100192/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200193 * show info on storage devices; 'usb start/init' must be invoked earlier
194 * as we only retrieve structures populated during devices initialization
195 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100196int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200197{
198 int i;
199
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100200 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200201 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100202 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200203 dev_print(&usb_dev_desc[i]);
204 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100205 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100206 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700207
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100208 printf("No storage devices, perhaps not 'usb start'ed..?\n");
209 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200210}
211
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200212static unsigned int usb_get_max_lun(struct us_data *us)
213{
214 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530215 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200216 len = usb_control_msg(us->pusb_dev,
217 usb_rcvctrlpipe(us->pusb_dev, 0),
218 US_BBB_GET_MAX_LUN,
219 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
220 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530221 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200222 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530223 debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
Puneet Saxenaf5766132012-04-03 14:56:06 +0530224 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200225}
226
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100227/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200228 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000229 * to the user if mode = 1
230 * returns current device or -1 if no
231 */
232int usb_stor_scan(int mode)
233{
234 unsigned char i;
235 struct usb_device *dev;
236
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100237 if (mode == 1)
Lucas Stach93c25822012-09-26 00:14:36 +0200238 printf(" scanning usb for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100239
wdenkaffae2b2002-08-17 09:36:01 +0000240 usb_disable_asynch(1); /* asynch transfer not allowed */
241
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100242 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
243 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 usb_dev_desc[i].if_type = IF_TYPE_USB;
245 usb_dev_desc[i].dev = i;
246 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200247 usb_dev_desc[i].target = 0xff;
248 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100249 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530250 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000251 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200252
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100253 usb_max_devs = 0;
254 for (i = 0; i < USB_MAX_DEVICE; i++) {
255 dev = usb_get_dev_index(i); /* get device */
Vivek Gautamceb49722013-04-12 16:34:33 +0530256 debug("i=%d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100257 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100258 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100259
260 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200261 /* OK, it's a storage device. Iterate over its LUNs
262 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100263 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200264 int lun, max_lun, start = usb_max_devs;
265
266 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
267 for (lun = 0;
268 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
269 lun++) {
270 usb_dev_desc[usb_max_devs].lun = lun;
271 if (usb_stor_get_info(dev, &usb_stor[start],
Vivek Gautam605bd752013-04-12 16:34:34 +0530272 &usb_dev_desc[usb_max_devs]) == 1) {
273 usb_max_devs++;
274 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200275 }
276 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100277 /* if storage device */
278 if (usb_max_devs == USB_MAX_STOR_DEV) {
279 printf("max USB Storage Device reached: %d stopping\n",
280 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000281 break;
282 }
283 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200284
wdenkaffae2b2002-08-17 09:36:01 +0000285 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200286 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100287 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000288 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100289 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000290}
291
292static int usb_stor_irq(struct usb_device *dev)
293{
294 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100295 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000296
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100297 if (us->ip_wanted)
298 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000299 return 0;
300}
301
302
Vivek Gautamceb49722013-04-12 16:34:33 +0530303#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000304
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100305static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000306{
307 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100308 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
309 for (i = 0; i < 12; i++)
310 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000311 printf("\n");
312}
313
314static void display_int_status(unsigned long tmp)
315{
316 printf("Status: %s %s %s %s %s %s %s\n",
317 (tmp & USB_ST_ACTIVE) ? "Active" : "",
318 (tmp & USB_ST_STALLED) ? "Stalled" : "",
319 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
320 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
321 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
322 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
323 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
324}
325#endif
326/***********************************************************************
327 * Data transfer routines
328 ***********************************************************************/
329
330static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
331{
332 int max_size;
333 int this_xfer;
334 int result;
335 int partial;
336 int maxtry;
337 int stat;
338
339 /* determine the maximum packet size for these transfers */
340 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
341
342 /* while we have data left to transfer */
343 while (length) {
344
345 /* calculate how long this will be -- maximum or a remainder */
346 this_xfer = length > max_size ? max_size : length;
347 length -= this_xfer;
348
349 /* setup the retry counter */
350 maxtry = 10;
351
352 /* set up the transfer loop */
353 do {
354 /* transfer the data */
Vivek Gautamceb49722013-04-12 16:34:33 +0530355 debug("Bulk xfer 0x%x(%d) try #%d\n",
356 (unsigned int)buf, this_xfer, 11 - maxtry);
wdenkaffae2b2002-08-17 09:36:01 +0000357 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100358 this_xfer, &partial,
359 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530360 debug("bulk_msg returned %d xferred %d/%d\n",
361 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100362 if (us->pusb_dev->status != 0) {
363 /* if we stall, we need to clear it before
364 * we go on
365 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530366#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000367 display_int_status(us->pusb_dev->status);
368#endif
369 if (us->pusb_dev->status & USB_ST_STALLED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530370 debug("stalled ->clearing endpoint" \
371 "halt for pipe 0x%x\n", pipe);
wdenkaffae2b2002-08-17 09:36:01 +0000372 stat = us->pusb_dev->status;
373 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100374 us->pusb_dev->status = stat;
375 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530376 debug("bulk transferred" \
377 "with error %lX," \
378 " but data ok\n",
379 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000380 return 0;
381 }
382 else
383 return result;
384 }
385 if (us->pusb_dev->status & USB_ST_NAK_REC) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530386 debug("Device NAKed bulk_msg\n");
wdenkaffae2b2002-08-17 09:36:01 +0000387 return result;
388 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530389 debug("bulk transferred with error");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100390 if (this_xfer == partial) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530391 debug(" %ld, but data ok\n",
392 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000393 return 0;
394 }
395 /* if our try counter reaches 0, bail out */
Vivek Gautamceb49722013-04-12 16:34:33 +0530396 debug(" %ld, data %d\n",
397 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000398 if (!maxtry--)
399 return result;
400 }
401 /* update to show what data was transferred */
402 this_xfer -= partial;
403 buf += partial;
404 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100405 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000406 }
407
408 /* if we get here, we're done and successful */
409 return 0;
410}
411
wdenk149dded2003-09-10 18:20:28 +0000412static int usb_stor_BBB_reset(struct us_data *us)
413{
414 int result;
415 unsigned int pipe;
416
417 /*
418 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
419 *
420 * For Reset Recovery the host shall issue in the following order:
421 * a) a Bulk-Only Mass Storage Reset
422 * b) a Clear Feature HALT to the Bulk-In endpoint
423 * c) a Clear Feature HALT to the Bulk-Out endpoint
424 *
425 * This is done in 3 steps.
426 *
427 * If the reset doesn't succeed, the device should be port reset.
428 *
429 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
430 */
Vivek Gautamceb49722013-04-12 16:34:33 +0530431 debug("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100432 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
433 US_BBB_RESET,
434 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
Kim Phillips199adb62012-10-29 13:34:32 +0000435 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200436
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100437 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530438 debug("RESET:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000439 return -1;
440 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200441
wdenk149dded2003-09-10 18:20:28 +0000442 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000443 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530444 debug("BBB_reset result %d: status %lX reset\n",
445 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000446 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
447 result = usb_clear_halt(us->pusb_dev, pipe);
448 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000449 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530450 debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
451 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000452 /* long wait for reset */
453 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
454 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000455 mdelay(150);
Vivek Gautamceb49722013-04-12 16:34:33 +0530456 debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
457 result, us->pusb_dev->status);
458 debug("BBB_reset done\n");
wdenk149dded2003-09-10 18:20:28 +0000459 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
Vivek Gautamceb49722013-04-12 16:34:33 +0530471 debug("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);
Vivek Gautamceb49722013-04-12 16:34:33 +0530483 debug("CB_reset result %d: status %lX clearing endpoint halt\n",
484 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000485 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
486 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
487
Vivek Gautamceb49722013-04-12 16:34:33 +0530488 debug("CB_reset done\n");
wdenkaffae2b2002-08-17 09:36:01 +0000489 return 0;
490}
491
wdenk149dded2003-09-10 18:20:28 +0000492/*
493 * Set up the command for a BBB device. Note that the actual SCSI
494 * command is copied into cbw.CBWCDB.
495 */
Kim Phillips199adb62012-10-29 13:34:32 +0000496static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000497{
498 int result;
499 int actlen;
500 int dir_in;
501 unsigned int pipe;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530502 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000503
504 dir_in = US_DIRECTION(srb->cmd[0]);
505
506#ifdef BBB_COMDAT_TRACE
Vivek Gautam605bd752013-04-12 16:34:34 +0530507 printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100508 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
509 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000510 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100511 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000512 printf("cmd[%d] %#x ", result, srb->cmd[result]);
513 printf("\n");
514 }
515#endif
516 /* sanity checks */
517 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530518 debug("usb_stor_BBB_comdat:cmdlen too large\n");
wdenk149dded2003-09-10 18:20:28 +0000519 return -1;
520 }
521
522 /* always OUT to the ep */
523 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
524
Puneet Saxenaf5766132012-04-03 14:56:06 +0530525 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
526 cbw->dCBWTag = cpu_to_le32(CBWTag++);
527 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
528 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
529 cbw->bCBWLUN = srb->lun;
530 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000531 /* copy the command data into the CBW command data buffer */
532 /* DST SRC LEN!!! */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530533 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
534 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100535 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000536 if (result < 0)
Vivek Gautamceb49722013-04-12 16:34:33 +0530537 debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
wdenk149dded2003-09-10 18:20:28 +0000538 return result;
539}
540
wdenkaffae2b2002-08-17 09:36:01 +0000541/* FIXME: we also need a CBI_command which sets up the completion
542 * interrupt, and waits for it
543 */
Kim Phillips199adb62012-10-29 13:34:32 +0000544static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000545{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200546 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100547 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000548 unsigned int pipe;
549 unsigned long status;
550
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100551 retry = 5;
552 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000553
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100554 if (dir_in)
555 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
556 else
557 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
558
559 while (retry--) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530560 debug("CBI gets a command: Try %d\n", 5 - retry);
561#ifdef DEBUG
wdenkaffae2b2002-08-17 09:36:01 +0000562 usb_show_srb(srb);
563#endif
564 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100565 result = usb_control_msg(us->pusb_dev,
566 usb_sndctrlpipe(us->pusb_dev , 0),
567 US_CBI_ADSC,
568 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000569 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100570 srb->cmd, srb->cmdlen,
571 USB_CNTL_TIMEOUT * 5);
Vivek Gautamceb49722013-04-12 16:34:33 +0530572 debug("CB_transport: control msg returned %d, status %lX\n",
573 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000574 /* check the return code for the command */
575 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100576 if (us->pusb_dev->status & USB_ST_STALLED) {
577 status = us->pusb_dev->status;
Vivek Gautamceb49722013-04-12 16:34:33 +0530578 debug(" stall during command found," \
579 " clear pipe\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100580 usb_clear_halt(us->pusb_dev,
581 usb_sndctrlpipe(us->pusb_dev, 0));
582 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000583 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530584 debug(" error during command %02X" \
585 " Stat = %lX\n", srb->cmd[0],
586 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000587 return result;
588 }
589 /* transfer the data payload for this command, if one exists*/
590
Vivek Gautamceb49722013-04-12 16:34:33 +0530591 debug("CB_transport: control msg returned %d," \
592 " direction is %s to go 0x%lx\n", result,
593 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000594 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100595 result = us_one_transfer(us, pipe, (char *)srb->pdata,
596 srb->datalen);
Vivek Gautamceb49722013-04-12 16:34:33 +0530597 debug("CBI attempted to transfer data," \
598 " result is %d status %lX, len %d\n",
599 result, us->pusb_dev->status,
600 us->pusb_dev->act_len);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100601 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000602 break;
603 } /* if (srb->datalen) */
604 else
605 break;
606 }
607 /* return result */
608
609 return result;
610}
611
612
Kim Phillips199adb62012-10-29 13:34:32 +0000613static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000614{
615 int timeout;
616
wdenk80885a92004-02-26 23:46:20 +0000617 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100618 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000619 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
620 timeout = 1000;
621 while (timeout--) {
Kim Phillips199adb62012-10-29 13:34:32 +0000622 if ((volatile int *) us->ip_wanted == NULL)
wdenkaffae2b2002-08-17 09:36:01 +0000623 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000624 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000625 }
626 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100627 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000628 us->ip_wanted = 0;
629 return USB_STOR_TRANSPORT_ERROR;
630 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530631 debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
632 us->ip_data, us->pusb_dev->irq_act_len,
633 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000634 /* UFI gives us ASC and ASCQ, like a request sense */
635 if (us->subclass == US_SC_UFI) {
636 if (srb->cmd[0] == SCSI_REQ_SENSE ||
637 srb->cmd[0] == SCSI_INQUIRY)
638 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000639 else if (us->ip_data)
640 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000641 else
wdenk80885a92004-02-26 23:46:20 +0000642 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000643 }
644 /* otherwise, we interpret the data normally */
645 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000646 case 0x0001:
647 return USB_STOR_TRANSPORT_GOOD;
648 case 0x0002:
649 return USB_STOR_TRANSPORT_FAILED;
650 default:
651 return USB_STOR_TRANSPORT_ERROR;
652 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000653 return USB_STOR_TRANSPORT_ERROR;
654}
655
656#define USB_TRANSPORT_UNKNOWN_RETRY 5
657#define USB_TRANSPORT_NOT_READY_RETRY 10
658
wdenk149dded2003-09-10 18:20:28 +0000659/* clear a stall on an endpoint - special for BBB devices */
Kim Phillips199adb62012-10-29 13:34:32 +0000660static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
wdenk149dded2003-09-10 18:20:28 +0000661{
662 int result;
663
664 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100665 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000666 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Kim Phillips199adb62012-10-29 13:34:32 +0000667 0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000668 return result;
669}
670
Kim Phillips199adb62012-10-29 13:34:32 +0000671static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
wdenk149dded2003-09-10 18:20:28 +0000672{
673 int result, retry;
674 int dir_in;
675 int actlen, data_actlen;
676 unsigned int pipe, pipein, pipeout;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530677 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000678#ifdef BBB_XPORT_TRACE
679 unsigned char *ptr;
680 int index;
681#endif
682
683 dir_in = US_DIRECTION(srb->cmd[0]);
684
685 /* COMMAND phase */
Vivek Gautamceb49722013-04-12 16:34:33 +0530686 debug("COMMAND phase\n");
wdenk149dded2003-09-10 18:20:28 +0000687 result = usb_stor_BBB_comdat(srb, us);
688 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530689 debug("failed to send CBW status %ld\n",
690 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000691 usb_stor_BBB_reset(us);
692 return USB_STOR_TRANSPORT_FAILED;
693 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200694 if (!(us->flags & USB_READY))
695 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000696 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
697 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
698 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000699 data_actlen = 0;
700 /* no data, go immediately to the STATUS phase */
701 if (srb->datalen == 0)
702 goto st;
Vivek Gautamceb49722013-04-12 16:34:33 +0530703 debug("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000704 if (dir_in)
705 pipe = pipein;
706 else
707 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100708 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
709 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000710 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100711 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530712 debug("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000713 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100714 result = usb_stor_BBB_clear_endpt_stall(us,
715 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000716 if (result >= 0)
717 /* continue on to STATUS phase */
718 goto st;
719 }
720 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530721 debug("usb_bulk_msg error status %ld\n",
722 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000723 usb_stor_BBB_reset(us);
724 return USB_STOR_TRANSPORT_FAILED;
725 }
726#ifdef BBB_XPORT_TRACE
727 for (index = 0; index < data_actlen; index++)
728 printf("pdata[%d] %#x ", index, srb->pdata[index]);
729 printf("\n");
730#endif
731 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100732st:
wdenk149dded2003-09-10 18:20:28 +0000733 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100734again:
Vivek Gautamceb49722013-04-12 16:34:33 +0530735 debug("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530736 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200737 &actlen, USB_CNTL_TIMEOUT*5);
738
wdenk149dded2003-09-10 18:20:28 +0000739 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100740 if ((result < 0) && (retry < 1) &&
741 (us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530742 debug("STATUS:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000743 /* clear the STALL on the endpoint */
744 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
745 if (result >= 0 && (retry++ < 1))
746 /* do a retry */
747 goto again;
748 }
749 if (result < 0) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530750 debug("usb_bulk_msg error status %ld\n",
751 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000752 usb_stor_BBB_reset(us);
753 return USB_STOR_TRANSPORT_FAILED;
754 }
755#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530756 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000757 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
758 printf("ptr[%d] %#x ", index, ptr[index]);
759 printf("\n");
760#endif
761 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530762 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000763 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
764 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530765 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530766 debug("!CSWSIGNATURE\n");
wdenk149dded2003-09-10 18:20:28 +0000767 usb_stor_BBB_reset(us);
768 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530769 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530770 debug("!Tag\n");
wdenk149dded2003-09-10 18:20:28 +0000771 usb_stor_BBB_reset(us);
772 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530773 } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530774 debug(">PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000775 usb_stor_BBB_reset(us);
776 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530777 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530778 debug("=PHASE\n");
wdenk149dded2003-09-10 18:20:28 +0000779 usb_stor_BBB_reset(us);
780 return USB_STOR_TRANSPORT_FAILED;
781 } else if (data_actlen > srb->datalen) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530782 debug("transferred %dB instead of %ldB\n",
783 data_actlen, srb->datalen);
wdenk149dded2003-09-10 18:20:28 +0000784 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530785 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530786 debug("FAILED\n");
wdenk149dded2003-09-10 18:20:28 +0000787 return USB_STOR_TRANSPORT_FAILED;
788 }
789
790 return result;
791}
792
Kim Phillips199adb62012-10-29 13:34:32 +0000793static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000794{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100795 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000796 ccb *psrb;
797 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100798 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000799
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200800 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100801 status = USB_STOR_TRANSPORT_GOOD;
802 retry = 0;
803 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000804 /* issue the command */
805do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 result = usb_stor_CB_comdat(srb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530807 debug("command / Data returned %d, status %lX\n",
808 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000809 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100810 if (us->protocol == US_PR_CBI) {
811 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000812 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100813 if (status == USB_STOR_TRANSPORT_ERROR) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530814 debug(" USB CBI Command Error\n");
wdenkaffae2b2002-08-17 09:36:01 +0000815 return status;
816 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100817 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
818 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
819 if (!us->ip_data) {
820 /* if the status is good, report it */
821 if (status == USB_STOR_TRANSPORT_GOOD) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530822 debug(" USB CBI Command Good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000823 return status;
824 }
825 }
826 }
827 /* do we have to issue an auto request? */
828 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100829 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530830 debug("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000831 us->transport_reset(us);
832 return USB_STOR_TRANSPORT_ERROR;
833 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100834 if ((us->protocol == US_PR_CBI) &&
835 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
836 (srb->cmd[0] == SCSI_INQUIRY))) {
837 /* do not issue an autorequest after request sense */
Vivek Gautamceb49722013-04-12 16:34:33 +0530838 debug("No auto request and good\n");
wdenkaffae2b2002-08-17 09:36:01 +0000839 return USB_STOR_TRANSPORT_GOOD;
840 }
841 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100842 memset(&psrb->cmd[0], 0, 12);
843 psrb->cmd[0] = SCSI_REQ_SENSE;
844 psrb->cmd[1] = srb->lun << 5;
845 psrb->cmd[4] = 18;
846 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200847 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100848 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000849 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100850 result = usb_stor_CB_comdat(psrb, us);
Vivek Gautamceb49722013-04-12 16:34:33 +0530851 debug("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000852 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 if (us->protocol == US_PR_CBI)
854 status = usb_stor_CBI_get_status(psrb, us);
855
856 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Vivek Gautamceb49722013-04-12 16:34:33 +0530857 debug(" AUTO REQUEST ERROR %ld\n",
858 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000859 return USB_STOR_TRANSPORT_ERROR;
860 }
Vivek Gautamceb49722013-04-12 16:34:33 +0530861 debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
862 srb->sense_buf[0], srb->sense_buf[2],
863 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000864 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100865 if ((srb->sense_buf[2] == 0) &&
866 (srb->sense_buf[12] == 0) &&
867 (srb->sense_buf[13] == 0)) {
868 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000869 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 }
871
wdenkaffae2b2002-08-17 09:36:01 +0000872 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100873 switch (srb->sense_buf[2]) {
874 case 0x01:
875 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000876 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000877 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878 case 0x02:
879 /* Not Ready */
880 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
881 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
882 " 0x%02X (NOT READY)\n", srb->cmd[0],
883 srb->sense_buf[0], srb->sense_buf[2],
884 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000885 return USB_STOR_TRANSPORT_FAILED;
886 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000887 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000888 goto do_retry;
889 }
890 break;
891 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100892 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
893 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
894 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
895 srb->sense_buf[2], srb->sense_buf[12],
896 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000897 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100898 } else
wdenk149dded2003-09-10 18:20:28 +0000899 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000900 break;
wdenkaffae2b2002-08-17 09:36:01 +0000901 }
902 return USB_STOR_TRANSPORT_FAILED;
903}
904
905
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100906static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000907{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100908 int retry, i;
909 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000910 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911 memset(&srb->cmd[0], 0, 12);
912 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200913 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100914 srb->cmd[4] = 36;
915 srb->datalen = 36;
916 srb->cmdlen = 12;
917 i = ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530918 debug("inquiry returns %d\n", i);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100919 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000920 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200921 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000922
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100923 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000924 printf("error in inquiry\n");
925 return -1;
926 }
927 return 0;
928}
929
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100930static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000931{
932 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000933
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100934 ptr = (char *)srb->pdata;
935 memset(&srb->cmd[0], 0, 12);
936 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200937 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100938 srb->cmd[4] = 18;
939 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200940 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100941 srb->cmdlen = 12;
942 ss->transport(srb, ss);
Vivek Gautamceb49722013-04-12 16:34:33 +0530943 debug("Request Sense returned %02X %02X %02X\n",
944 srb->sense_buf[2], srb->sense_buf[12],
945 srb->sense_buf[13]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100946 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000947 return 0;
948}
949
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100950static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000951{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200952 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000953
wdenkaffae2b2002-08-17 09:36:01 +0000954 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955 memset(&srb->cmd[0], 0, 12);
956 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200957 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100958 srb->datalen = 0;
959 srb->cmdlen = 12;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200960 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
961 ss->flags |= USB_READY;
wdenkaffae2b2002-08-17 09:36:01 +0000962 return 0;
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +0200963 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100964 usb_request_sense(srb, ss);
Vincent Palatin8b57e2f2012-12-12 17:55:29 -0800965 /*
966 * Check the Key Code Qualifier, if it matches
967 * "Not Ready - medium not present"
968 * (the sense Key equals 0x2 and the ASC is 0x3a)
969 * return immediately as the medium being absent won't change
970 * unless there is a user action.
971 */
972 if ((srb->sense_buf[2] == 0x02) &&
973 (srb->sense_buf[12] == 0x3a))
974 return -1;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000975 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100976 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000977
wdenkaffae2b2002-08-17 09:36:01 +0000978 return -1;
979}
980
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100981static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000982{
983 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100984 /* XXX retries */
985 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000986 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 memset(&srb->cmd[0], 0, 12);
988 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200989 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100990 srb->datalen = 8;
991 srb->cmdlen = 12;
992 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000993 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100994 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000995
wdenkaffae2b2002-08-17 09:36:01 +0000996 return -1;
997}
998
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100999static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
1000 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +00001001{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001002 memset(&srb->cmd[0], 0, 12);
1003 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001004 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001005 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1006 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1007 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1008 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1009 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1010 srb->cmd[8] = (unsigned char) blocks & 0xff;
1011 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301012 debug("read10: start %lx blocks %x\n", start, blocks);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001013 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001014}
1015
Mahavir Jain127e1082009-11-03 12:22:10 +05301016static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1017 unsigned short blocks)
1018{
1019 memset(&srb->cmd[0], 0, 12);
1020 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001021 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301022 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1023 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1024 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1025 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1026 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1027 srb->cmd[8] = (unsigned char) blocks & 0xff;
1028 srb->cmdlen = 12;
Vivek Gautamceb49722013-04-12 16:34:33 +05301029 debug("write10: start %lx blocks %x\n", start, blocks);
Mahavir Jain127e1082009-11-03 12:22:10 +05301030 return ss->transport(srb, ss);
1031}
1032
wdenkaffae2b2002-08-17 09:36:01 +00001033
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001034#ifdef CONFIG_USB_BIN_FIXUP
1035/*
1036 * Some USB storage devices queried for SCSI identification data respond with
1037 * binary strings, which if output to the console freeze the terminal. The
1038 * workaround is to modify the vendor and product strings read from such
1039 * device with proper values (as reported by 'usb info').
1040 *
1041 * Vendor and product length limits are taken from the definition of
1042 * block_dev_desc_t in include/part.h.
1043 */
1044static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1045 unsigned char vendor[],
1046 unsigned char product[]) {
1047 const unsigned char max_vendor_len = 40;
1048 const unsigned char max_product_len = 20;
1049 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050 strncpy((char *)vendor, "SMSC", max_vendor_len);
1051 strncpy((char *)product, "Flash Media Cntrller",
1052 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001053 }
1054}
1055#endif /* CONFIG_USB_BIN_FIXUP */
1056
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057unsigned long usb_stor_read(int device, unsigned long blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001058 lbaint_t blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001059{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001060 lbaint_t start, blks;
1061 uintptr_t buf_addr;
wdenkaffae2b2002-08-17 09:36:01 +00001062 unsigned short smallblks;
1063 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001064 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001065 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001066 ccb *srb = &usb_ccb;
1067
1068 if (blkcnt == 0)
1069 return 0;
1070
1071 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001072 /* Setup device */
Vivek Gautamceb49722013-04-12 16:34:33 +05301073 debug("\nusb_read: dev %d \n", device);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001074 dev = NULL;
1075 for (i = 0; i < USB_MAX_DEVICE; i++) {
1076 dev = usb_get_dev_index(i);
1077 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001078 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001079 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001080 break;
1081 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001082 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001083
1084 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001085 srb->lun = usb_dev_desc[device].lun;
1086 buf_addr = (unsigned long)buffer;
1087 start = blknr;
1088 blks = blkcnt;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001089
Vivek Gautamceb49722013-04-12 16:34:33 +05301090 debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
1091 " buffer %lx\n", device, start, blks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092
wdenkaffae2b2002-08-17 09:36:01 +00001093 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001094 /* XXX need some comment here */
1095 retry = 2;
1096 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001097 if (blks > USB_MAX_XFER_BLK)
1098 smallblks = USB_MAX_XFER_BLK;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001099 else
1100 smallblks = (unsigned short) blks;
wdenkaffae2b2002-08-17 09:36:01 +00001101retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001102 if (smallblks == USB_MAX_XFER_BLK)
wdenkaffae2b2002-08-17 09:36:01 +00001103 usb_show_progress();
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001104 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1105 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001106 if (usb_read_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301107 debug("Read ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001108 usb_request_sense(srb, ss);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001109 if (retry--)
wdenkaffae2b2002-08-17 09:36:01 +00001110 goto retry_it;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001111 blkcnt -= blks;
wdenkaffae2b2002-08-17 09:36:01 +00001112 break;
1113 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001114 start += smallblks;
1115 blks -= smallblks;
1116 buf_addr += srb->datalen;
1117 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001118 ss->flags &= ~USB_READY;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001119
Vivek Gautamceb49722013-04-12 16:34:33 +05301120 debug("usb_read: end startblk " LBAF
1121 ", blccnt %x buffer %lx\n",
1122 start, smallblks, buf_addr);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001123
wdenkaffae2b2002-08-17 09:36:01 +00001124 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001125 if (blkcnt >= USB_MAX_XFER_BLK)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001126 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001127 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001128}
1129
Mahavir Jain127e1082009-11-03 12:22:10 +05301130unsigned long usb_stor_write(int device, unsigned long blknr,
Gabe Blacke81e79e2012-10-12 14:26:07 +00001131 lbaint_t blkcnt, const void *buffer)
Mahavir Jain127e1082009-11-03 12:22:10 +05301132{
Gabe Blacke81e79e2012-10-12 14:26:07 +00001133 lbaint_t start, blks;
1134 uintptr_t buf_addr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301135 unsigned short smallblks;
1136 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001137 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301138 int retry, i;
1139 ccb *srb = &usb_ccb;
1140
1141 if (blkcnt == 0)
1142 return 0;
1143
1144 device &= 0xff;
1145 /* Setup device */
Vivek Gautamceb49722013-04-12 16:34:33 +05301146 debug("\nusb_write: dev %d \n", device);
Mahavir Jain127e1082009-11-03 12:22:10 +05301147 dev = NULL;
1148 for (i = 0; i < USB_MAX_DEVICE; i++) {
1149 dev = usb_get_dev_index(i);
1150 if (dev == NULL)
1151 return 0;
1152 if (dev->devnum == usb_dev_desc[device].target)
1153 break;
1154 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001155 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301156
1157 usb_disable_asynch(1); /* asynch transfer not allowed */
1158
1159 srb->lun = usb_dev_desc[device].lun;
1160 buf_addr = (unsigned long)buffer;
1161 start = blknr;
1162 blks = blkcnt;
Mahavir Jain127e1082009-11-03 12:22:10 +05301163
Vivek Gautamceb49722013-04-12 16:34:33 +05301164 debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
1165 " buffer %lx\n", device, start, blks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301166
1167 do {
1168 /* If write fails retry for max retry count else
1169 * return with number of blocks written successfully.
1170 */
1171 retry = 2;
1172 srb->pdata = (unsigned char *)buf_addr;
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001173 if (blks > USB_MAX_XFER_BLK)
1174 smallblks = USB_MAX_XFER_BLK;
Mahavir Jain127e1082009-11-03 12:22:10 +05301175 else
1176 smallblks = (unsigned short) blks;
1177retry_it:
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001178 if (smallblks == USB_MAX_XFER_BLK)
Mahavir Jain127e1082009-11-03 12:22:10 +05301179 usb_show_progress();
1180 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1181 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001182 if (usb_write_10(srb, ss, start, smallblks)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301183 debug("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001184 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301185 if (retry--)
1186 goto retry_it;
1187 blkcnt -= blks;
1188 break;
1189 }
1190 start += smallblks;
1191 blks -= smallblks;
1192 buf_addr += srb->datalen;
1193 } while (blks != 0);
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001194 ss->flags &= ~USB_READY;
Mahavir Jain127e1082009-11-03 12:22:10 +05301195
Vivek Gautamceb49722013-04-12 16:34:33 +05301196 debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
1197 start, smallblks, buf_addr);
Mahavir Jain127e1082009-11-03 12:22:10 +05301198
1199 usb_disable_asynch(0); /* asynch transfer allowed */
Benoît Thébaudeau4bee5c82012-08-10 18:23:25 +02001200 if (blkcnt >= USB_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;
Vivek Gautam605bd752013-04-12 16:34:34 +05301212 struct usb_endpoint_descriptor *ep_desc;
wdenkaffae2b2002-08-17 09:36:01 +00001213 unsigned int flags = 0;
1214
1215 int protocol = 0;
1216 int subclass = 0;
1217
wdenkaffae2b2002-08-17 09:36:01 +00001218 /* let's examine the device now */
1219 iface = &dev->config.if_desc[ifnum];
1220
1221#if 0
1222 /* this is the place to patch some storage devices */
Vivek Gautamceb49722013-04-12 16:34:33 +05301223 debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001224 dev->descriptor.idProduct);
1225
1226 if ((dev->descriptor.idVendor) == 0x066b &&
1227 (dev->descriptor.idProduct) == 0x0103) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301228 debug("patched for E-USB\n");
wdenkaffae2b2002-08-17 09:36:01 +00001229 protocol = US_PR_CB;
1230 subclass = US_SC_UFI; /* an assumption */
1231 }
1232#endif
1233
1234 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001235 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1236 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1237 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001238 /* if it's not a mass storage, we go no further */
1239 return 0;
1240 }
1241
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001242 memset(ss, 0, sizeof(struct us_data));
1243
wdenkaffae2b2002-08-17 09:36:01 +00001244 /* At this point, we know we've got a live one */
Vivek Gautamceb49722013-04-12 16:34:33 +05301245 debug("\n\nUSB Mass Storage device detected\n");
wdenkaffae2b2002-08-17 09:36:01 +00001246
1247 /* Initialize the us_data structure with some useful info */
1248 ss->flags = flags;
1249 ss->ifnum = ifnum;
1250 ss->pusb_dev = dev;
1251 ss->attention_done = 0;
1252
1253 /* If the device has subclass and protocol, then use that. Otherwise,
1254 * take data from the specific interface.
1255 */
1256 if (subclass) {
1257 ss->subclass = subclass;
1258 ss->protocol = protocol;
1259 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001260 ss->subclass = iface->desc.bInterfaceSubClass;
1261 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001262 }
1263
1264 /* set the handler pointers based on the protocol */
Vivek Gautamceb49722013-04-12 16:34:33 +05301265 debug("Transport: ");
wdenkaffae2b2002-08-17 09:36:01 +00001266 switch (ss->protocol) {
1267 case US_PR_CB:
Vivek Gautamceb49722013-04-12 16:34:33 +05301268 debug("Control/Bulk\n");
wdenkaffae2b2002-08-17 09:36:01 +00001269 ss->transport = usb_stor_CB_transport;
1270 ss->transport_reset = usb_stor_CB_reset;
1271 break;
1272
1273 case US_PR_CBI:
Vivek Gautamceb49722013-04-12 16:34:33 +05301274 debug("Control/Bulk/Interrupt\n");
wdenkaffae2b2002-08-17 09:36:01 +00001275 ss->transport = usb_stor_CB_transport;
1276 ss->transport_reset = usb_stor_CB_reset;
1277 break;
wdenk149dded2003-09-10 18:20:28 +00001278 case US_PR_BULK:
Vivek Gautamceb49722013-04-12 16:34:33 +05301279 debug("Bulk/Bulk/Bulk\n");
wdenk149dded2003-09-10 18:20:28 +00001280 ss->transport = usb_stor_BBB_transport;
1281 ss->transport_reset = usb_stor_BBB_reset;
1282 break;
wdenkaffae2b2002-08-17 09:36:01 +00001283 default:
wdenk80885a92004-02-26 23:46:20 +00001284 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001285 return 0;
1286 break;
1287 }
1288
1289 /*
1290 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1291 * An optional interrupt is OK (necessary for CBI protocol).
1292 * We will ignore any others.
1293 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001294 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301295 ep_desc = &iface->ep_desc[i];
wdenkaffae2b2002-08-17 09:36:01 +00001296 /* is it an BULK endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301297 if ((ep_desc->bmAttributes &
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001298 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
Vivek Gautam605bd752013-04-12 16:34:34 +05301299 if (ep_desc->bEndpointAddress & USB_DIR_IN)
1300 ss->ep_in = ep_desc->bEndpointAddress &
1301 USB_ENDPOINT_NUMBER_MASK;
wdenkaffae2b2002-08-17 09:36:01 +00001302 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001303 ss->ep_out =
Vivek Gautam605bd752013-04-12 16:34:34 +05301304 ep_desc->bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001305 USB_ENDPOINT_NUMBER_MASK;
1306 }
1307
1308 /* is it an interrupt endpoint? */
Vivek Gautam605bd752013-04-12 16:34:34 +05301309 if ((ep_desc->bmAttributes &
1310 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1311 ss->ep_int = ep_desc->bEndpointAddress &
1312 USB_ENDPOINT_NUMBER_MASK;
1313 ss->irqinterval = ep_desc->bInterval;
wdenkaffae2b2002-08-17 09:36:01 +00001314 }
1315 }
Vivek Gautamceb49722013-04-12 16:34:33 +05301316 debug("Endpoints In %d Out %d Int %d\n",
1317 ss->ep_in, ss->ep_out, ss->ep_int);
wdenkaffae2b2002-08-17 09:36:01 +00001318
1319 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001320 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001321 !ss->ep_in || !ss->ep_out ||
1322 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
Vivek Gautamceb49722013-04-12 16:34:33 +05301323 debug("Problems with device\n");
wdenkaffae2b2002-08-17 09:36:01 +00001324 return 0;
1325 }
1326 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001327 /* We only handle certain protocols. Currently, these are
1328 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001329 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001330 */
wdenk80885a92004-02-26 23:46:20 +00001331 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1332 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001333 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001334 return 0;
1335 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001336 if (ss->ep_int) {
1337 /* we had found an interrupt endpoint, prepare irq pipe
1338 * set up the IRQ pipe and handler
1339 */
wdenkaffae2b2002-08-17 09:36:01 +00001340 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1341 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1342 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001343 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001344 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001345 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001346 return 1;
1347}
1348
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001349int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1350 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001351{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001352 unsigned char perq, modi;
Puneet Saxenaf5766132012-04-03 14:56:06 +05301353 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1354 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001355 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001356 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001357
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001358 pccb->pdata = usb_stor_buf;
1359
1360 dev_desc->target = dev->devnum;
1361 pccb->lun = dev_desc->lun;
Vivek Gautamceb49722013-04-12 16:34:33 +05301362 debug(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001363
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001364 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001365 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001366
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001367 perq = usb_stor_buf[0];
1368 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001369
1370 if ((perq & 0x1f) == 0x1f) {
1371 /* skip unknown devices */
1372 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001373 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001374 if ((modi&0x80) == 0x80) {
1375 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001376 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001377 }
Puneet Saxenaf5766132012-04-03 14:56:06 +05301378 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1379 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1380 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001381 dev_desc->vendor[8] = 0;
1382 dev_desc->product[16] = 0;
1383 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001384#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001385 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1386 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001387#endif /* CONFIG_USB_BIN_FIXUP */
Vivek Gautamceb49722013-04-12 16:34:33 +05301388 debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1389 usb_stor_buf[3]);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001390 if (usb_test_unit_ready(pccb, ss)) {
1391 printf("Device NOT ready\n"
1392 " Request Sense returned %02X %02X %02X\n",
1393 pccb->sense_buf[2], pccb->sense_buf[12],
1394 pccb->sense_buf[13]);
1395 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001396 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001397 return 1;
1398 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001399 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001400 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001401 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001402 memset(pccb->pdata, 0, 8);
1403 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001404 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001405 cap[0] = 2880;
1406 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001407 }
Benoît Thébaudeau3e8581b2012-08-10 18:27:11 +02001408 ss->flags &= ~USB_READY;
Vivek Gautamceb49722013-04-12 16:34:33 +05301409 debug("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001410#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001411 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1412 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001413#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001414 cap[0] = cpu_to_be32(cap[0]);
1415 cap[1] = cpu_to_be32(cap[1]);
1416
wdenk149dded2003-09-10 18:20:28 +00001417 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001418 cap[0] += 1;
1419 capacity = &cap[0];
1420 blksz = &cap[1];
Vivek Gautamceb49722013-04-12 16:34:33 +05301421 debug("Capacity = 0x%lx, blocksz = 0x%lx\n", *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001422 dev_desc->lba = *capacity;
1423 dev_desc->blksz = *blksz;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001424 dev_desc->log2blksz = LOG2(dev_desc->blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001425 dev_desc->type = perq;
Vivek Gautamceb49722013-04-12 16:34:33 +05301426 debug(" address %d\n", dev_desc->target);
1427 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001428
1429 init_part(dev_desc);
1430
Vivek Gautamceb49722013-04-12 16:34:33 +05301431 debug("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001432 return 1;
1433}