blob: 0cd6399a3c42a228a71c28290a649efc0864cdd4 [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
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200158#ifdef CONFIG_USB_EHCI
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000159/*
160 * The U-Boot EHCI driver cannot handle more than 5 page aligned buffers
161 * of 4096 bytes in a transfer without running itself out of qt_buffers
162 */
163#define USB_MAX_XFER_BLK(start, blksz) (((4096 * 5) - (start % 4096)) / blksz)
Benoît Thébaudeaucffcc502012-08-10 18:26:50 +0200164#else
165#define USB_MAX_XFER_BLK(start, blksz) 20
166#endif
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +0000167
wdenkaffae2b2002-08-17 09:36:01 +0000168static struct us_data usb_stor[USB_MAX_STOR_DEV];
169
170
wdenk80885a92004-02-26 23:46:20 +0000171#define USB_STOR_TRANSPORT_GOOD 0
wdenkaffae2b2002-08-17 09:36:01 +0000172#define USB_STOR_TRANSPORT_FAILED -1
173#define USB_STOR_TRANSPORT_ERROR -2
174
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100175int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
176 block_dev_desc_t *dev_desc);
177int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
178 struct us_data *ss);
179unsigned long usb_stor_read(int device, unsigned long blknr,
180 unsigned long blkcnt, void *buffer);
Mahavir Jain127e1082009-11-03 12:22:10 +0530181unsigned long usb_stor_write(int device, unsigned long blknr,
182 unsigned long blkcnt, const void *buffer);
wdenkaffae2b2002-08-17 09:36:01 +0000183struct usb_device * usb_get_dev_index(int index);
184void uhci_show_temp_int_td(void);
185
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000186#ifdef CONFIG_PARTITIONS
wdenkaffae2b2002-08-17 09:36:01 +0000187block_dev_desc_t *usb_stor_get_dev(int index)
188{
Kim B. Heinoaaad1082010-03-12 15:46:56 +0200189 return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
wdenkaffae2b2002-08-17 09:36:01 +0000190}
Matthew McClintockdf3fc522011-05-24 05:31:19 +0000191#endif
wdenkaffae2b2002-08-17 09:36:01 +0000192
193void usb_show_progress(void)
194{
Wolfgang Denk226fa9b2010-07-19 11:36:59 +0200195 debug(".");
wdenkaffae2b2002-08-17 09:36:01 +0000196}
197
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100198/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200199 * show info on storage devices; 'usb start/init' must be invoked earlier
200 * as we only retrieve structures populated during devices initialization
201 */
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100202int usb_stor_info(void)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200203{
204 int i;
205
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100206 if (usb_max_devs > 0) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200207 for (i = 0; i < usb_max_devs; i++) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100208 printf(" Device %d: ", i);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200209 dev_print(&usb_dev_desc[i]);
210 }
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100211 return 0;
Aras Vaichasf6b44e02008-03-25 12:09:07 +1100212 }
Wolfgang Denk1aeed8d2008-04-13 09:59:26 -0700213
Markus Klotzbuecherb9e749e2008-03-26 18:26:43 +0100214 printf("No storage devices, perhaps not 'usb start'ed..?\n");
215 return 1;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200216}
217
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200218static unsigned int usb_get_max_lun(struct us_data *us)
219{
220 int len;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530221 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200222 len = usb_control_msg(us->pusb_dev,
223 usb_rcvctrlpipe(us->pusb_dev, 0),
224 US_BBB_GET_MAX_LUN,
225 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
226 0, us->ifnum,
Puneet Saxenaf5766132012-04-03 14:56:06 +0530227 result, sizeof(char),
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200228 USB_CNTL_TIMEOUT * 5);
229 USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
Puneet Saxenaf5766132012-04-03 14:56:06 +0530230 len, (int) *result);
231 return (len > 0) ? *result : 0;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200232}
233
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100234/*******************************************************************************
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200235 * scan the usb and reports device info
wdenkaffae2b2002-08-17 09:36:01 +0000236 * to the user if mode = 1
237 * returns current device or -1 if no
238 */
239int usb_stor_scan(int mode)
240{
241 unsigned char i;
242 struct usb_device *dev;
243
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100244 if (mode == 1)
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200245 printf(" scanning bus for storage devices... ");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100246
wdenkaffae2b2002-08-17 09:36:01 +0000247 usb_disable_asynch(1); /* asynch transfer not allowed */
248
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100249 for (i = 0; i < USB_MAX_STOR_DEV; i++) {
250 memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100251 usb_dev_desc[i].if_type = IF_TYPE_USB;
252 usb_dev_desc[i].dev = i;
253 usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
Wolfgang Denka17c5482010-07-19 11:36:56 +0200254 usb_dev_desc[i].target = 0xff;
255 usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100256 usb_dev_desc[i].block_read = usb_stor_read;
Mahavir Jain127e1082009-11-03 12:22:10 +0530257 usb_dev_desc[i].block_write = usb_stor_write;
wdenkaffae2b2002-08-17 09:36:01 +0000258 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200259
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100260 usb_max_devs = 0;
261 for (i = 0; i < USB_MAX_DEVICE; i++) {
262 dev = usb_get_dev_index(i); /* get device */
263 USB_STOR_PRINTF("i=%d\n", i);
264 if (dev == NULL)
Loïc Minier6052cba2011-02-03 22:04:26 +0100265 break; /* no more devices available */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100266
267 if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200268 /* OK, it's a storage device. Iterate over its LUNs
269 * and populate `usb_dev_desc'.
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100270 */
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200271 int lun, max_lun, start = usb_max_devs;
272
273 max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
274 for (lun = 0;
275 lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
276 lun++) {
277 usb_dev_desc[usb_max_devs].lun = lun;
278 if (usb_stor_get_info(dev, &usb_stor[start],
279 &usb_dev_desc[usb_max_devs]) == 1) {
wdenkaffae2b2002-08-17 09:36:01 +0000280 usb_max_devs++;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100281 }
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200282 }
283 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100284 /* if storage device */
285 if (usb_max_devs == USB_MAX_STOR_DEV) {
286 printf("max USB Storage Device reached: %d stopping\n",
287 usb_max_devs);
wdenkaffae2b2002-08-17 09:36:01 +0000288 break;
289 }
290 } /* for */
Wolfgang Denk095b8a32005-08-02 17:06:17 +0200291
wdenkaffae2b2002-08-17 09:36:01 +0000292 usb_disable_asynch(0); /* asynch transfer allowed */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200293 printf("%d Storage Device(s) found\n", usb_max_devs);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100294 if (usb_max_devs > 0)
wdenkaffae2b2002-08-17 09:36:01 +0000295 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100296 return -1;
wdenkaffae2b2002-08-17 09:36:01 +0000297}
298
299static int usb_stor_irq(struct usb_device *dev)
300{
301 struct us_data *us;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100302 us = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +0000303
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100304 if (us->ip_wanted)
305 us->ip_wanted = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000306 return 0;
307}
308
309
310#ifdef USB_STOR_DEBUG
311
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100312static void usb_show_srb(ccb *pccb)
wdenkaffae2b2002-08-17 09:36:01 +0000313{
314 int i;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100315 printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
316 for (i = 0; i < 12; i++)
317 printf("%02X ", pccb->cmd[i]);
wdenkaffae2b2002-08-17 09:36:01 +0000318 printf("\n");
319}
320
321static void display_int_status(unsigned long tmp)
322{
323 printf("Status: %s %s %s %s %s %s %s\n",
324 (tmp & USB_ST_ACTIVE) ? "Active" : "",
325 (tmp & USB_ST_STALLED) ? "Stalled" : "",
326 (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
327 (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
328 (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
329 (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
330 (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
331}
332#endif
333/***********************************************************************
334 * Data transfer routines
335 ***********************************************************************/
336
337static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
338{
339 int max_size;
340 int this_xfer;
341 int result;
342 int partial;
343 int maxtry;
344 int stat;
345
346 /* determine the maximum packet size for these transfers */
347 max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
348
349 /* while we have data left to transfer */
350 while (length) {
351
352 /* calculate how long this will be -- maximum or a remainder */
353 this_xfer = length > max_size ? max_size : length;
354 length -= this_xfer;
355
356 /* setup the retry counter */
357 maxtry = 10;
358
359 /* set up the transfer loop */
360 do {
361 /* transfer the data */
362 USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
363 (unsigned int)buf, this_xfer, 11 - maxtry);
364 result = usb_bulk_msg(us->pusb_dev, pipe, buf,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100365 this_xfer, &partial,
366 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000367 USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
368 result, partial, this_xfer);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100369 if (us->pusb_dev->status != 0) {
370 /* if we stall, we need to clear it before
371 * we go on
372 */
wdenkaffae2b2002-08-17 09:36:01 +0000373#ifdef USB_STOR_DEBUG
374 display_int_status(us->pusb_dev->status);
375#endif
376 if (us->pusb_dev->status & USB_ST_STALLED) {
377 USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
378 stat = us->pusb_dev->status;
379 usb_clear_halt(us->pusb_dev, pipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100380 us->pusb_dev->status = stat;
381 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200382 USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000383 return 0;
384 }
385 else
386 return result;
387 }
388 if (us->pusb_dev->status & USB_ST_NAK_REC) {
389 USB_STOR_PRINTF("Device NAKed bulk_msg\n");
390 return result;
391 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100392 USB_STOR_PRINTF("bulk transferred with error");
393 if (this_xfer == partial) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200394 USB_STOR_PRINTF(" %ld, but data ok\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100395 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000396 return 0;
397 }
398 /* if our try counter reaches 0, bail out */
Marek Vasut4b210e82011-10-25 11:39:17 +0200399 USB_STOR_PRINTF(" %ld, data %d\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100400 us->pusb_dev->status, partial);
wdenkaffae2b2002-08-17 09:36:01 +0000401 if (!maxtry--)
402 return result;
403 }
404 /* update to show what data was transferred */
405 this_xfer -= partial;
406 buf += partial;
407 /* continue until this transfer is done */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100408 } while (this_xfer);
wdenkaffae2b2002-08-17 09:36:01 +0000409 }
410
411 /* if we get here, we're done and successful */
412 return 0;
413}
414
wdenk149dded2003-09-10 18:20:28 +0000415static int usb_stor_BBB_reset(struct us_data *us)
416{
417 int result;
418 unsigned int pipe;
419
420 /*
421 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
422 *
423 * For Reset Recovery the host shall issue in the following order:
424 * a) a Bulk-Only Mass Storage Reset
425 * b) a Clear Feature HALT to the Bulk-In endpoint
426 * c) a Clear Feature HALT to the Bulk-Out endpoint
427 *
428 * This is done in 3 steps.
429 *
430 * If the reset doesn't succeed, the device should be port reset.
431 *
432 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
433 */
434 USB_STOR_PRINTF("BBB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100435 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
436 US_BBB_RESET,
437 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
438 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT * 5);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200439
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100440 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000441 USB_STOR_PRINTF("RESET:stall\n");
442 return -1;
443 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200444
wdenk149dded2003-09-10 18:20:28 +0000445 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000446 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200447 USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100448 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000449 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
450 result = usb_clear_halt(us->pusb_dev, pipe);
451 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000452 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200453 USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100454 result, us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000455 /* long wait for reset */
456 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
457 result = usb_clear_halt(us->pusb_dev, pipe);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000458 mdelay(150);
Marek Vasut4b210e82011-10-25 11:39:17 +0200459 USB_STOR_PRINTF("BBB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100460 " clearing OUT endpoint\n", result,
461 us->pusb_dev->status);
wdenk149dded2003-09-10 18:20:28 +0000462 USB_STOR_PRINTF("BBB_reset done\n");
463 return 0;
464}
465
wdenkaffae2b2002-08-17 09:36:01 +0000466/* FIXME: this reset function doesn't really reset the port, and it
467 * should. Actually it should probably do what it's doing here, and
468 * reset the port physically
469 */
470static int usb_stor_CB_reset(struct us_data *us)
471{
472 unsigned char cmd[12];
473 int result;
474
475 USB_STOR_PRINTF("CB_reset\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100476 memset(cmd, 0xff, sizeof(cmd));
wdenkaffae2b2002-08-17 09:36:01 +0000477 cmd[0] = SCSI_SEND_DIAG;
478 cmd[1] = 4;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100479 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
480 US_CBI_ADSC,
481 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
482 0, us->ifnum, cmd, sizeof(cmd),
483 USB_CNTL_TIMEOUT * 5);
wdenkaffae2b2002-08-17 09:36:01 +0000484
485 /* long wait for reset */
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000486 mdelay(1500);
Marek Vasut4b210e82011-10-25 11:39:17 +0200487 USB_STOR_PRINTF("CB_reset result %d: status %lX"
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100488 " clearing endpoint halt\n", result,
489 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000490 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
491 usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
492
493 USB_STOR_PRINTF("CB_reset done\n");
494 return 0;
495}
496
wdenk149dded2003-09-10 18:20:28 +0000497/*
498 * Set up the command for a BBB device. Note that the actual SCSI
499 * command is copied into cbw.CBWCDB.
500 */
501int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
502{
503 int result;
504 int actlen;
505 int dir_in;
506 unsigned int pipe;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530507 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
wdenk149dded2003-09-10 18:20:28 +0000508
509 dir_in = US_DIRECTION(srb->cmd[0]);
510
511#ifdef BBB_COMDAT_TRACE
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100512 printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
513 dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
514 srb->pdata);
wdenk149dded2003-09-10 18:20:28 +0000515 if (srb->cmdlen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100516 for (result = 0; result < srb->cmdlen; result++)
wdenk149dded2003-09-10 18:20:28 +0000517 printf("cmd[%d] %#x ", result, srb->cmd[result]);
518 printf("\n");
519 }
520#endif
521 /* sanity checks */
522 if (!(srb->cmdlen <= CBWCDBLENGTH)) {
523 USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
524 return -1;
525 }
526
527 /* always OUT to the ep */
528 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
529
Puneet Saxenaf5766132012-04-03 14:56:06 +0530530 cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
531 cbw->dCBWTag = cpu_to_le32(CBWTag++);
532 cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
533 cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
534 cbw->bCBWLUN = srb->lun;
535 cbw->bCDBLength = srb->cmdlen;
wdenk149dded2003-09-10 18:20:28 +0000536 /* copy the command data into the CBW command data buffer */
537 /* DST SRC LEN!!! */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530538 memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
539 result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100540 &actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000541 if (result < 0)
542 USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
543 return result;
544}
545
wdenkaffae2b2002-08-17 09:36:01 +0000546/* FIXME: we also need a CBI_command which sets up the completion
547 * interrupt, and waits for it
548 */
549int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
550{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200551 int result = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100552 int dir_in, retry;
wdenkaffae2b2002-08-17 09:36:01 +0000553 unsigned int pipe;
554 unsigned long status;
555
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100556 retry = 5;
557 dir_in = US_DIRECTION(srb->cmd[0]);
wdenkaffae2b2002-08-17 09:36:01 +0000558
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100559 if (dir_in)
560 pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
561 else
562 pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
563
564 while (retry--) {
565 USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
wdenkaffae2b2002-08-17 09:36:01 +0000566#ifdef USB_STOR_DEBUG
567 usb_show_srb(srb);
568#endif
569 /* let's send the command via the control pipe */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100570 result = usb_control_msg(us->pusb_dev,
571 usb_sndctrlpipe(us->pusb_dev , 0),
572 US_CBI_ADSC,
573 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
wdenkaffae2b2002-08-17 09:36:01 +0000574 0, us->ifnum,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100575 srb->cmd, srb->cmdlen,
576 USB_CNTL_TIMEOUT * 5);
577 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
Marek Vasut4b210e82011-10-25 11:39:17 +0200578 " status %lX\n", result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000579 /* check the return code for the command */
580 if (result < 0) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100581 if (us->pusb_dev->status & USB_ST_STALLED) {
582 status = us->pusb_dev->status;
583 USB_STOR_PRINTF(" stall during command found,"
584 " clear pipe\n");
585 usb_clear_halt(us->pusb_dev,
586 usb_sndctrlpipe(us->pusb_dev, 0));
587 us->pusb_dev->status = status;
wdenkaffae2b2002-08-17 09:36:01 +0000588 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100589 USB_STOR_PRINTF(" error during command %02X"
Marek Vasut4b210e82011-10-25 11:39:17 +0200590 " Stat = %lX\n", srb->cmd[0],
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100591 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000592 return result;
593 }
594 /* transfer the data payload for this command, if one exists*/
595
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100596 USB_STOR_PRINTF("CB_transport: control msg returned %d,"
597 " direction is %s to go 0x%lx\n", result,
598 dir_in ? "IN" : "OUT", srb->datalen);
wdenkaffae2b2002-08-17 09:36:01 +0000599 if (srb->datalen) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100600 result = us_one_transfer(us, pipe, (char *)srb->pdata,
601 srb->datalen);
602 USB_STOR_PRINTF("CBI attempted to transfer data,"
603 " result is %d status %lX, len %d\n",
604 result, us->pusb_dev->status,
605 us->pusb_dev->act_len);
606 if (!(us->pusb_dev->status & USB_ST_NAK_REC))
wdenkaffae2b2002-08-17 09:36:01 +0000607 break;
608 } /* if (srb->datalen) */
609 else
610 break;
611 }
612 /* return result */
613
614 return result;
615}
616
617
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100618int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
wdenkaffae2b2002-08-17 09:36:01 +0000619{
620 int timeout;
621
wdenk80885a92004-02-26 23:46:20 +0000622 us->ip_wanted = 1;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100623 submit_int_msg(us->pusb_dev, us->irqpipe,
wdenk80885a92004-02-26 23:46:20 +0000624 (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
625 timeout = 1000;
626 while (timeout--) {
627 if ((volatile int *) us->ip_wanted == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000628 break;
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000629 mdelay(10);
wdenkaffae2b2002-08-17 09:36:01 +0000630 }
631 if (us->ip_wanted) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100632 printf(" Did not get interrupt on CBI\n");
wdenkaffae2b2002-08-17 09:36:01 +0000633 us->ip_wanted = 0;
634 return USB_STOR_TRANSPORT_ERROR;
635 }
wdenk80885a92004-02-26 23:46:20 +0000636 USB_STOR_PRINTF
637 ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
638 us->ip_data, us->pusb_dev->irq_act_len,
639 us->pusb_dev->irq_status);
wdenkaffae2b2002-08-17 09:36:01 +0000640 /* UFI gives us ASC and ASCQ, like a request sense */
641 if (us->subclass == US_SC_UFI) {
642 if (srb->cmd[0] == SCSI_REQ_SENSE ||
643 srb->cmd[0] == SCSI_INQUIRY)
644 return USB_STOR_TRANSPORT_GOOD; /* Good */
wdenk80885a92004-02-26 23:46:20 +0000645 else if (us->ip_data)
646 return USB_STOR_TRANSPORT_FAILED;
wdenkaffae2b2002-08-17 09:36:01 +0000647 else
wdenk80885a92004-02-26 23:46:20 +0000648 return USB_STOR_TRANSPORT_GOOD;
wdenkaffae2b2002-08-17 09:36:01 +0000649 }
650 /* otherwise, we interpret the data normally */
651 switch (us->ip_data) {
wdenk80885a92004-02-26 23:46:20 +0000652 case 0x0001:
653 return USB_STOR_TRANSPORT_GOOD;
654 case 0x0002:
655 return USB_STOR_TRANSPORT_FAILED;
656 default:
657 return USB_STOR_TRANSPORT_ERROR;
658 } /* switch */
wdenkaffae2b2002-08-17 09:36:01 +0000659 return USB_STOR_TRANSPORT_ERROR;
660}
661
662#define USB_TRANSPORT_UNKNOWN_RETRY 5
663#define USB_TRANSPORT_NOT_READY_RETRY 10
664
wdenk149dded2003-09-10 18:20:28 +0000665/* clear a stall on an endpoint - special for BBB devices */
666int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
667{
668 int result;
669
670 /* ENDPOINT_HALT = 0, so set value to 0 */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100671 result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
wdenk149dded2003-09-10 18:20:28 +0000672 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100673 0, endpt, 0, 0, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000674 return result;
675}
676
677int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
678{
679 int result, retry;
680 int dir_in;
681 int actlen, data_actlen;
682 unsigned int pipe, pipein, pipeout;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530683 ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
wdenk149dded2003-09-10 18:20:28 +0000684#ifdef BBB_XPORT_TRACE
685 unsigned char *ptr;
686 int index;
687#endif
688
689 dir_in = US_DIRECTION(srb->cmd[0]);
690
691 /* COMMAND phase */
692 USB_STOR_PRINTF("COMMAND phase\n");
693 result = usb_stor_BBB_comdat(srb, us);
694 if (result < 0) {
695 USB_STOR_PRINTF("failed to send CBW status %ld\n",
696 us->pusb_dev->status);
697 usb_stor_BBB_reset(us);
698 return USB_STOR_TRANSPORT_FAILED;
699 }
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000700 mdelay(5);
wdenk149dded2003-09-10 18:20:28 +0000701 pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
702 pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
703 /* DATA phase + error handling */
wdenk149dded2003-09-10 18:20:28 +0000704 data_actlen = 0;
705 /* no data, go immediately to the STATUS phase */
706 if (srb->datalen == 0)
707 goto st;
wdenk80885a92004-02-26 23:46:20 +0000708 USB_STOR_PRINTF("DATA phase\n");
wdenk149dded2003-09-10 18:20:28 +0000709 if (dir_in)
710 pipe = pipein;
711 else
712 pipe = pipeout;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100713 result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
714 &data_actlen, USB_CNTL_TIMEOUT * 5);
wdenk149dded2003-09-10 18:20:28 +0000715 /* special handling of STALL in DATA phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100716 if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
wdenka43278a2003-09-11 19:48:06 +0000717 USB_STOR_PRINTF("DATA:stall\n");
wdenk149dded2003-09-10 18:20:28 +0000718 /* clear the STALL on the endpoint */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100719 result = usb_stor_BBB_clear_endpt_stall(us,
720 dir_in ? us->ep_in : us->ep_out);
wdenk149dded2003-09-10 18:20:28 +0000721 if (result >= 0)
722 /* continue on to STATUS phase */
723 goto st;
724 }
725 if (result < 0) {
726 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
727 us->pusb_dev->status);
728 usb_stor_BBB_reset(us);
729 return USB_STOR_TRANSPORT_FAILED;
730 }
731#ifdef BBB_XPORT_TRACE
732 for (index = 0; index < data_actlen; index++)
733 printf("pdata[%d] %#x ", index, srb->pdata[index]);
734 printf("\n");
735#endif
736 /* STATUS phase + error handling */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100737st:
wdenk149dded2003-09-10 18:20:28 +0000738 retry = 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100739again:
wdenk149dded2003-09-10 18:20:28 +0000740 USB_STOR_PRINTF("STATUS phase\n");
Puneet Saxenaf5766132012-04-03 14:56:06 +0530741 result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200742 &actlen, USB_CNTL_TIMEOUT*5);
743
wdenk149dded2003-09-10 18:20:28 +0000744 /* special handling of STALL in STATUS phase */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100745 if ((result < 0) && (retry < 1) &&
746 (us->pusb_dev->status & USB_ST_STALLED)) {
wdenk149dded2003-09-10 18:20:28 +0000747 USB_STOR_PRINTF("STATUS:stall\n");
748 /* clear the STALL on the endpoint */
749 result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
750 if (result >= 0 && (retry++ < 1))
751 /* do a retry */
752 goto again;
753 }
754 if (result < 0) {
755 USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
756 us->pusb_dev->status);
757 usb_stor_BBB_reset(us);
758 return USB_STOR_TRANSPORT_FAILED;
759 }
760#ifdef BBB_XPORT_TRACE
Puneet Saxenaf5766132012-04-03 14:56:06 +0530761 ptr = (unsigned char *)csw;
wdenk149dded2003-09-10 18:20:28 +0000762 for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
763 printf("ptr[%d] %#x ", index, ptr[index]);
764 printf("\n");
765#endif
766 /* misuse pipe to get the residue */
Puneet Saxenaf5766132012-04-03 14:56:06 +0530767 pipe = le32_to_cpu(csw->dCSWDataResidue);
wdenk149dded2003-09-10 18:20:28 +0000768 if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
769 pipe = srb->datalen - data_actlen;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530770 if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
wdenk149dded2003-09-10 18:20:28 +0000771 USB_STOR_PRINTF("!CSWSIGNATURE\n");
772 usb_stor_BBB_reset(us);
773 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530774 } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
wdenk149dded2003-09-10 18:20:28 +0000775 USB_STOR_PRINTF("!Tag\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;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530782 } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
wdenk149dded2003-09-10 18:20:28 +0000783 USB_STOR_PRINTF("=PHASE\n");
784 usb_stor_BBB_reset(us);
785 return USB_STOR_TRANSPORT_FAILED;
786 } else if (data_actlen > srb->datalen) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200787 USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
wdenk149dded2003-09-10 18:20:28 +0000788 data_actlen, srb->datalen);
789 return USB_STOR_TRANSPORT_FAILED;
Puneet Saxenaf5766132012-04-03 14:56:06 +0530790 } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
wdenk149dded2003-09-10 18:20:28 +0000791 USB_STOR_PRINTF("FAILED\n");
792 return USB_STOR_TRANSPORT_FAILED;
793 }
794
795 return result;
796}
797
wdenkaffae2b2002-08-17 09:36:01 +0000798int usb_stor_CB_transport(ccb *srb, struct us_data *us)
799{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100800 int result, status;
wdenkaffae2b2002-08-17 09:36:01 +0000801 ccb *psrb;
802 ccb reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100803 int retry, notready;
wdenkaffae2b2002-08-17 09:36:01 +0000804
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200805 psrb = &reqsrb;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100806 status = USB_STOR_TRANSPORT_GOOD;
807 retry = 0;
808 notready = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000809 /* issue the command */
810do_retry:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100811 result = usb_stor_CB_comdat(srb, us);
Marek Vasut4b210e82011-10-25 11:39:17 +0200812 USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100813 result, us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000814 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100815 if (us->protocol == US_PR_CBI) {
816 status = usb_stor_CBI_get_status(srb, us);
wdenkaffae2b2002-08-17 09:36:01 +0000817 /* if the status is error, report it */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100818 if (status == USB_STOR_TRANSPORT_ERROR) {
wdenkaffae2b2002-08-17 09:36:01 +0000819 USB_STOR_PRINTF(" USB CBI Command Error\n");
820 return status;
821 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100822 srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
823 srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
824 if (!us->ip_data) {
825 /* if the status is good, report it */
826 if (status == USB_STOR_TRANSPORT_GOOD) {
wdenkaffae2b2002-08-17 09:36:01 +0000827 USB_STOR_PRINTF(" USB CBI Command Good\n");
828 return status;
829 }
830 }
831 }
832 /* do we have to issue an auto request? */
833 /* HERE we have to check the result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100834 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200835 USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000836 us->transport_reset(us);
837 return USB_STOR_TRANSPORT_ERROR;
838 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100839 if ((us->protocol == US_PR_CBI) &&
840 ((srb->cmd[0] == SCSI_REQ_SENSE) ||
841 (srb->cmd[0] == SCSI_INQUIRY))) {
842 /* do not issue an autorequest after request sense */
wdenkaffae2b2002-08-17 09:36:01 +0000843 USB_STOR_PRINTF("No auto request and good\n");
844 return USB_STOR_TRANSPORT_GOOD;
845 }
846 /* issue an request_sense */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100847 memset(&psrb->cmd[0], 0, 12);
848 psrb->cmd[0] = SCSI_REQ_SENSE;
849 psrb->cmd[1] = srb->lun << 5;
850 psrb->cmd[4] = 18;
851 psrb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200852 psrb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100853 psrb->cmdlen = 12;
wdenkaffae2b2002-08-17 09:36:01 +0000854 /* issue the command */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100855 result = usb_stor_CB_comdat(psrb, us);
856 USB_STOR_PRINTF("auto request returned %d\n", result);
wdenkaffae2b2002-08-17 09:36:01 +0000857 /* if this is an CBI Protocol, get IRQ */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100858 if (us->protocol == US_PR_CBI)
859 status = usb_stor_CBI_get_status(psrb, us);
860
861 if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
Marek Vasut4b210e82011-10-25 11:39:17 +0200862 USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100863 us->pusb_dev->status);
wdenkaffae2b2002-08-17 09:36:01 +0000864 return USB_STOR_TRANSPORT_ERROR;
865 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100866 USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
867 srb->sense_buf[0], srb->sense_buf[2],
868 srb->sense_buf[12], srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +0000869 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100870 if ((srb->sense_buf[2] == 0) &&
871 (srb->sense_buf[12] == 0) &&
872 (srb->sense_buf[13] == 0)) {
873 /* ok, no sense */
wdenkaffae2b2002-08-17 09:36:01 +0000874 return USB_STOR_TRANSPORT_GOOD;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100875 }
876
wdenkaffae2b2002-08-17 09:36:01 +0000877 /* Check the auto request result */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100878 switch (srb->sense_buf[2]) {
879 case 0x01:
880 /* Recovered Error */
wdenk149dded2003-09-10 18:20:28 +0000881 return USB_STOR_TRANSPORT_GOOD;
wdenk80885a92004-02-26 23:46:20 +0000882 break;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100883 case 0x02:
884 /* Not Ready */
885 if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
886 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
887 " 0x%02X (NOT READY)\n", srb->cmd[0],
888 srb->sense_buf[0], srb->sense_buf[2],
889 srb->sense_buf[12], srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000890 return USB_STOR_TRANSPORT_FAILED;
891 } else {
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000892 mdelay(100);
wdenk149dded2003-09-10 18:20:28 +0000893 goto do_retry;
894 }
895 break;
896 default:
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100897 if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
898 printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
899 " 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
900 srb->sense_buf[2], srb->sense_buf[12],
901 srb->sense_buf[13]);
wdenk149dded2003-09-10 18:20:28 +0000902 return USB_STOR_TRANSPORT_FAILED;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100903 } else
wdenk149dded2003-09-10 18:20:28 +0000904 goto do_retry;
wdenk149dded2003-09-10 18:20:28 +0000905 break;
wdenkaffae2b2002-08-17 09:36:01 +0000906 }
907 return USB_STOR_TRANSPORT_FAILED;
908}
909
910
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100911static int usb_inquiry(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000912{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100913 int retry, i;
914 retry = 5;
wdenkaffae2b2002-08-17 09:36:01 +0000915 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100916 memset(&srb->cmd[0], 0, 12);
917 srb->cmd[0] = SCSI_INQUIRY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200918 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100919 srb->cmd[4] = 36;
920 srb->datalen = 36;
921 srb->cmdlen = 12;
922 i = ss->transport(srb, ss);
923 USB_STOR_PRINTF("inquiry returns %d\n", i);
924 if (i == 0)
wdenkaffae2b2002-08-17 09:36:01 +0000925 break;
Kim B. Heinofac71cc2010-03-12 10:07:00 +0200926 } while (--retry);
wdenk149dded2003-09-10 18:20:28 +0000927
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100928 if (!retry) {
wdenkaffae2b2002-08-17 09:36:01 +0000929 printf("error in inquiry\n");
930 return -1;
931 }
932 return 0;
933}
934
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100935static int usb_request_sense(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000936{
937 char *ptr;
wdenk80885a92004-02-26 23:46:20 +0000938
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100939 ptr = (char *)srb->pdata;
940 memset(&srb->cmd[0], 0, 12);
941 srb->cmd[0] = SCSI_REQ_SENSE;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200942 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100943 srb->cmd[4] = 18;
944 srb->datalen = 18;
Wolfgang Denkd0ff51b2008-07-14 15:19:07 +0200945 srb->pdata = &srb->sense_buf[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100946 srb->cmdlen = 12;
947 ss->transport(srb, ss);
948 USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
949 srb->sense_buf[2], srb->sense_buf[12],
950 srb->sense_buf[13]);
951 srb->pdata = (uchar *)ptr;
wdenkaffae2b2002-08-17 09:36:01 +0000952 return 0;
953}
954
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100955static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000956{
Wolfgang Denk9c998aa2005-07-21 11:57:57 +0200957 int retries = 10;
wdenk149dded2003-09-10 18:20:28 +0000958
wdenkaffae2b2002-08-17 09:36:01 +0000959 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100960 memset(&srb->cmd[0], 0, 12);
961 srb->cmd[0] = SCSI_TST_U_RDY;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200962 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100963 srb->datalen = 0;
964 srb->cmdlen = 12;
965 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000966 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100967 usb_request_sense(srb, ss);
Mike Frysinger5b84dd62012-03-05 13:47:00 +0000968 mdelay(100);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100969 } while (retries--);
wdenk149dded2003-09-10 18:20:28 +0000970
wdenkaffae2b2002-08-17 09:36:01 +0000971 return -1;
972}
973
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100974static int usb_read_capacity(ccb *srb, struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +0000975{
976 int retry;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100977 /* XXX retries */
978 retry = 3;
wdenkaffae2b2002-08-17 09:36:01 +0000979 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100980 memset(&srb->cmd[0], 0, 12);
981 srb->cmd[0] = SCSI_RD_CAPAC;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200982 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100983 srb->datalen = 8;
984 srb->cmdlen = 12;
985 if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
wdenkaffae2b2002-08-17 09:36:01 +0000986 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100987 } while (retry--);
wdenk149dded2003-09-10 18:20:28 +0000988
wdenkaffae2b2002-08-17 09:36:01 +0000989 return -1;
990}
991
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100992static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
993 unsigned short blocks)
wdenkaffae2b2002-08-17 09:36:01 +0000994{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100995 memset(&srb->cmd[0], 0, 12);
996 srb->cmd[0] = SCSI_READ10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +0200997 srb->cmd[1] = srb->lun << 5;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +0100998 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
999 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1000 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1001 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1002 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1003 srb->cmd[8] = (unsigned char) blocks & 0xff;
1004 srb->cmdlen = 12;
1005 USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
1006 return ss->transport(srb, ss);
wdenkaffae2b2002-08-17 09:36:01 +00001007}
1008
Mahavir Jain127e1082009-11-03 12:22:10 +05301009static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
1010 unsigned short blocks)
1011{
1012 memset(&srb->cmd[0], 0, 12);
1013 srb->cmd[0] = SCSI_WRITE10;
Ludovic Courtès99e9ed12010-10-05 22:04:26 +02001014 srb->cmd[1] = srb->lun << 5;
Mahavir Jain127e1082009-11-03 12:22:10 +05301015 srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
1016 srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
1017 srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
1018 srb->cmd[5] = ((unsigned char) (start)) & 0xff;
1019 srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
1020 srb->cmd[8] = (unsigned char) blocks & 0xff;
1021 srb->cmdlen = 12;
1022 USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
1023 return ss->transport(srb, ss);
1024}
1025
wdenkaffae2b2002-08-17 09:36:01 +00001026
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001027#ifdef CONFIG_USB_BIN_FIXUP
1028/*
1029 * Some USB storage devices queried for SCSI identification data respond with
1030 * binary strings, which if output to the console freeze the terminal. The
1031 * workaround is to modify the vendor and product strings read from such
1032 * device with proper values (as reported by 'usb info').
1033 *
1034 * Vendor and product length limits are taken from the definition of
1035 * block_dev_desc_t in include/part.h.
1036 */
1037static void usb_bin_fixup(struct usb_device_descriptor descriptor,
1038 unsigned char vendor[],
1039 unsigned char product[]) {
1040 const unsigned char max_vendor_len = 40;
1041 const unsigned char max_product_len = 20;
1042 if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001043 strncpy((char *)vendor, "SMSC", max_vendor_len);
1044 strncpy((char *)product, "Flash Media Cntrller",
1045 max_product_len);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001046 }
1047}
1048#endif /* CONFIG_USB_BIN_FIXUP */
1049
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001050unsigned long usb_stor_read(int device, unsigned long blknr,
1051 unsigned long blkcnt, void *buffer)
wdenkaffae2b2002-08-17 09:36:01 +00001052{
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001053 unsigned long start, blks, buf_addr, max_xfer_blk;
wdenkaffae2b2002-08-17 09:36:01 +00001054 unsigned short smallblks;
1055 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001056 struct us_data *ss;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001057 int retry, i;
wdenkf8d813e2004-03-02 14:05:39 +00001058 ccb *srb = &usb_ccb;
1059
1060 if (blkcnt == 0)
1061 return 0;
1062
1063 device &= 0xff;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001064 /* Setup device */
1065 USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
1066 dev = NULL;
1067 for (i = 0; i < USB_MAX_DEVICE; i++) {
1068 dev = usb_get_dev_index(i);
1069 if (dev == NULL)
wdenkaffae2b2002-08-17 09:36:01 +00001070 return 0;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001071 if (dev->devnum == usb_dev_desc[device].target)
wdenkaffae2b2002-08-17 09:36:01 +00001072 break;
1073 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001074 ss = (struct us_data *)dev->privptr;
wdenkaffae2b2002-08-17 09:36:01 +00001075
1076 usb_disable_asynch(1); /* asynch transfer not allowed */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001077 srb->lun = usb_dev_desc[device].lun;
1078 buf_addr = (unsigned long)buffer;
1079 start = blknr;
1080 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001081 if (usb_test_unit_ready(srb, ss)) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001082 printf("Device NOT ready\n Request Sense returned %02X %02X"
1083 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1084 srb->sense_buf[13]);
wdenkaffae2b2002-08-17 09:36:01 +00001085 return 0;
1086 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001087
1088 USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
1089 " buffer %lx\n", device, start, blks, buf_addr);
1090
wdenkaffae2b2002-08-17 09:36:01 +00001091 do {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001092 /* XXX need some comment here */
1093 retry = 2;
1094 srb->pdata = (unsigned char *)buf_addr;
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001095 max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
1096 usb_dev_desc[device].blksz);
1097 if (blks > max_xfer_blk)
1098 smallblks = (unsigned short) 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:
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001102 if (smallblks == 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)) {
wdenkaffae2b2002-08-17 09:36:01 +00001107 USB_STOR_PRINTF("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);
1118
1119 USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
1120 start, smallblks, buf_addr);
1121
wdenkaffae2b2002-08-17 09:36:01 +00001122 usb_disable_asynch(0); /* asynch transfer allowed */
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001123 if (blkcnt >= max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001124 debug("\n");
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001125 return blkcnt;
wdenkaffae2b2002-08-17 09:36:01 +00001126}
1127
Mahavir Jain127e1082009-11-03 12:22:10 +05301128unsigned long usb_stor_write(int device, unsigned long blknr,
1129 unsigned long blkcnt, const void *buffer)
1130{
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001131 unsigned long start, blks, buf_addr, max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301132 unsigned short smallblks;
1133 struct usb_device *dev;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001134 struct us_data *ss;
Mahavir Jain127e1082009-11-03 12:22:10 +05301135 int retry, i;
1136 ccb *srb = &usb_ccb;
1137
1138 if (blkcnt == 0)
1139 return 0;
1140
1141 device &= 0xff;
1142 /* Setup device */
1143 USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
1144 dev = NULL;
1145 for (i = 0; i < USB_MAX_DEVICE; i++) {
1146 dev = usb_get_dev_index(i);
1147 if (dev == NULL)
1148 return 0;
1149 if (dev->devnum == usb_dev_desc[device].target)
1150 break;
1151 }
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001152 ss = (struct us_data *)dev->privptr;
Mahavir Jain127e1082009-11-03 12:22:10 +05301153
1154 usb_disable_asynch(1); /* asynch transfer not allowed */
1155
1156 srb->lun = usb_dev_desc[device].lun;
1157 buf_addr = (unsigned long)buffer;
1158 start = blknr;
1159 blks = blkcnt;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001160 if (usb_test_unit_ready(srb, ss)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301161 printf("Device NOT ready\n Request Sense returned %02X %02X"
1162 " %02X\n", srb->sense_buf[2], srb->sense_buf[12],
1163 srb->sense_buf[13]);
1164 return 0;
1165 }
1166
1167 USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx"
1168 " buffer %lx\n", device, start, blks, buf_addr);
1169
1170 do {
1171 /* If write fails retry for max retry count else
1172 * return with number of blocks written successfully.
1173 */
1174 retry = 2;
1175 srb->pdata = (unsigned char *)buf_addr;
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001176 max_xfer_blk = USB_MAX_XFER_BLK(buf_addr,
1177 usb_dev_desc[device].blksz);
1178 if (blks > max_xfer_blk)
1179 smallblks = (unsigned short) max_xfer_blk;
Mahavir Jain127e1082009-11-03 12:22:10 +05301180 else
1181 smallblks = (unsigned short) blks;
1182retry_it:
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001183 if (smallblks == max_xfer_blk)
Mahavir Jain127e1082009-11-03 12:22:10 +05301184 usb_show_progress();
1185 srb->datalen = usb_dev_desc[device].blksz * smallblks;
1186 srb->pdata = (unsigned char *)buf_addr;
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001187 if (usb_write_10(srb, ss, start, smallblks)) {
Mahavir Jain127e1082009-11-03 12:22:10 +05301188 USB_STOR_PRINTF("Write ERROR\n");
Kyle Moffett5dd95cf2011-12-21 07:08:12 +00001189 usb_request_sense(srb, ss);
Mahavir Jain127e1082009-11-03 12:22:10 +05301190 if (retry--)
1191 goto retry_it;
1192 blkcnt -= blks;
1193 break;
1194 }
1195 start += smallblks;
1196 blks -= smallblks;
1197 buf_addr += srb->datalen;
1198 } while (blks != 0);
1199
1200 USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
1201 start, smallblks, buf_addr);
1202
1203 usb_disable_asynch(0); /* asynch transfer allowed */
Stefan Herbrechtsmeier1b4bd0e2012-07-09 09:52:29 +00001204 if (blkcnt >= max_xfer_blk)
Wolfgang Denk226fa9b2010-07-19 11:36:59 +02001205 debug("\n");
Mahavir Jain127e1082009-11-03 12:22:10 +05301206 return blkcnt;
1207
1208}
wdenkaffae2b2002-08-17 09:36:01 +00001209
1210/* Probe to see if a new device is actually a Storage device */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001211int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
1212 struct us_data *ss)
wdenkaffae2b2002-08-17 09:36:01 +00001213{
Tom Rix8f8bd562009-10-31 12:37:38 -05001214 struct usb_interface *iface;
wdenkaffae2b2002-08-17 09:36:01 +00001215 int i;
1216 unsigned int flags = 0;
1217
1218 int protocol = 0;
1219 int subclass = 0;
1220
wdenkaffae2b2002-08-17 09:36:01 +00001221 /* let's examine the device now */
1222 iface = &dev->config.if_desc[ifnum];
1223
1224#if 0
1225 /* this is the place to patch some storage devices */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001226 USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
1227 dev->descriptor.idProduct);
1228
1229 if ((dev->descriptor.idVendor) == 0x066b &&
1230 (dev->descriptor.idProduct) == 0x0103) {
wdenkaffae2b2002-08-17 09:36:01 +00001231 USB_STOR_PRINTF("patched for E-USB\n");
1232 protocol = US_PR_CB;
1233 subclass = US_SC_UFI; /* an assumption */
1234 }
1235#endif
1236
1237 if (dev->descriptor.bDeviceClass != 0 ||
Tom Rix8f8bd562009-10-31 12:37:38 -05001238 iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
1239 iface->desc.bInterfaceSubClass < US_SC_MIN ||
1240 iface->desc.bInterfaceSubClass > US_SC_MAX) {
wdenkaffae2b2002-08-17 09:36:01 +00001241 /* if it's not a mass storage, we go no further */
1242 return 0;
1243 }
1244
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001245 memset(ss, 0, sizeof(struct us_data));
1246
wdenkaffae2b2002-08-17 09:36:01 +00001247 /* At this point, we know we've got a live one */
1248 USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
1249
1250 /* Initialize the us_data structure with some useful info */
1251 ss->flags = flags;
1252 ss->ifnum = ifnum;
1253 ss->pusb_dev = dev;
1254 ss->attention_done = 0;
1255
1256 /* If the device has subclass and protocol, then use that. Otherwise,
1257 * take data from the specific interface.
1258 */
1259 if (subclass) {
1260 ss->subclass = subclass;
1261 ss->protocol = protocol;
1262 } else {
Tom Rix8f8bd562009-10-31 12:37:38 -05001263 ss->subclass = iface->desc.bInterfaceSubClass;
1264 ss->protocol = iface->desc.bInterfaceProtocol;
wdenkaffae2b2002-08-17 09:36:01 +00001265 }
1266
1267 /* set the handler pointers based on the protocol */
1268 USB_STOR_PRINTF("Transport: ");
1269 switch (ss->protocol) {
1270 case US_PR_CB:
1271 USB_STOR_PRINTF("Control/Bulk\n");
1272 ss->transport = usb_stor_CB_transport;
1273 ss->transport_reset = usb_stor_CB_reset;
1274 break;
1275
1276 case US_PR_CBI:
1277 USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
1278 ss->transport = usb_stor_CB_transport;
1279 ss->transport_reset = usb_stor_CB_reset;
1280 break;
wdenk149dded2003-09-10 18:20:28 +00001281 case US_PR_BULK:
1282 USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
1283 ss->transport = usb_stor_BBB_transport;
1284 ss->transport_reset = usb_stor_BBB_reset;
1285 break;
wdenkaffae2b2002-08-17 09:36:01 +00001286 default:
wdenk80885a92004-02-26 23:46:20 +00001287 printf("USB Storage Transport unknown / not yet implemented\n");
wdenkaffae2b2002-08-17 09:36:01 +00001288 return 0;
1289 break;
1290 }
1291
1292 /*
1293 * We are expecting a minimum of 2 endpoints - in and out (bulk).
1294 * An optional interrupt is OK (necessary for CBI protocol).
1295 * We will ignore any others.
1296 */
Tom Rix8f8bd562009-10-31 12:37:38 -05001297 for (i = 0; i < iface->desc.bNumEndpoints; i++) {
wdenkaffae2b2002-08-17 09:36:01 +00001298 /* is it an BULK endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001299 if ((iface->ep_desc[i].bmAttributes &
1300 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
wdenkaffae2b2002-08-17 09:36:01 +00001301 if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
1302 ss->ep_in = iface->ep_desc[i].bEndpointAddress &
1303 USB_ENDPOINT_NUMBER_MASK;
1304 else
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001305 ss->ep_out =
1306 iface->ep_desc[i].bEndpointAddress &
wdenkaffae2b2002-08-17 09:36:01 +00001307 USB_ENDPOINT_NUMBER_MASK;
1308 }
1309
1310 /* is it an interrupt endpoint? */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001311 if ((iface->ep_desc[i].bmAttributes &
1312 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
wdenkaffae2b2002-08-17 09:36:01 +00001313 ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1314 USB_ENDPOINT_NUMBER_MASK;
1315 ss->irqinterval = iface->ep_desc[i].bInterval;
1316 }
1317 }
1318 USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
1319 ss->ep_in, ss->ep_out, ss->ep_int);
1320
1321 /* Do some basic sanity checks, and bail if we find a problem */
Tom Rix8f8bd562009-10-31 12:37:38 -05001322 if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
wdenkaffae2b2002-08-17 09:36:01 +00001323 !ss->ep_in || !ss->ep_out ||
1324 (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
1325 USB_STOR_PRINTF("Problems with device\n");
1326 return 0;
1327 }
1328 /* set class specific stuff */
wdenk149dded2003-09-10 18:20:28 +00001329 /* We only handle certain protocols. Currently, these are
1330 * the only ones.
wdenk80885a92004-02-26 23:46:20 +00001331 * The SFF8070 accepts the requests used in u-boot
wdenkaffae2b2002-08-17 09:36:01 +00001332 */
wdenk80885a92004-02-26 23:46:20 +00001333 if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
1334 ss->subclass != US_SC_8070) {
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001335 printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
wdenkaffae2b2002-08-17 09:36:01 +00001336 return 0;
1337 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001338 if (ss->ep_int) {
1339 /* we had found an interrupt endpoint, prepare irq pipe
1340 * set up the IRQ pipe and handler
1341 */
wdenkaffae2b2002-08-17 09:36:01 +00001342 ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
1343 ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
1344 ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001345 dev->irq_handle = usb_stor_irq;
wdenkaffae2b2002-08-17 09:36:01 +00001346 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001347 dev->privptr = (void *)ss;
wdenkaffae2b2002-08-17 09:36:01 +00001348 return 1;
1349}
1350
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001351int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
1352 block_dev_desc_t *dev_desc)
wdenkaffae2b2002-08-17 09:36:01 +00001353{
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001354 unsigned char perq, modi;
Puneet Saxenaf5766132012-04-03 14:56:06 +05301355 ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
1356 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001357 unsigned long *capacity, *blksz;
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001358 ccb *pccb = &usb_ccb;
wdenkaffae2b2002-08-17 09:36:01 +00001359
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001360 pccb->pdata = usb_stor_buf;
1361
1362 dev_desc->target = dev->devnum;
1363 pccb->lun = dev_desc->lun;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001364 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
wdenkaffae2b2002-08-17 09:36:01 +00001365
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001366 if (usb_inquiry(pccb, ss))
wdenkaffae2b2002-08-17 09:36:01 +00001367 return -1;
Wolfgang Denk095b8a32005-08-02 17:06:17 +02001368
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001369 perq = usb_stor_buf[0];
1370 modi = usb_stor_buf[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001371
1372 if ((perq & 0x1f) == 0x1f) {
1373 /* skip unknown devices */
1374 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001375 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001376 if ((modi&0x80) == 0x80) {
1377 /* drive is removable */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001378 dev_desc->removable = 1;
wdenkaffae2b2002-08-17 09:36:01 +00001379 }
Puneet Saxenaf5766132012-04-03 14:56:06 +05301380 memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
1381 memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
1382 memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001383 dev_desc->vendor[8] = 0;
1384 dev_desc->product[16] = 0;
1385 dev_desc->revision[4] = 0;
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001386#ifdef CONFIG_USB_BIN_FIXUP
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001387 usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
1388 (uchar *)dev_desc->product);
Bartlomiej Siekaddde6b72006-08-22 10:38:18 +02001389#endif /* CONFIG_USB_BIN_FIXUP */
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001390 USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
1391 usb_stor_buf[3]);
1392 if (usb_test_unit_ready(pccb, ss)) {
1393 printf("Device NOT ready\n"
1394 " Request Sense returned %02X %02X %02X\n",
1395 pccb->sense_buf[2], pccb->sense_buf[12],
1396 pccb->sense_buf[13]);
1397 if (dev_desc->removable == 1) {
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001398 dev_desc->type = perq;
wdenkaffae2b2002-08-17 09:36:01 +00001399 return 1;
1400 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001401 return 0;
wdenkaffae2b2002-08-17 09:36:01 +00001402 }
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001403 pccb->pdata = (unsigned char *)&cap[0];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001404 memset(pccb->pdata, 0, 8);
1405 if (usb_read_capacity(pccb, ss) != 0) {
wdenkaffae2b2002-08-17 09:36:01 +00001406 printf("READ_CAP ERROR\n");
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001407 cap[0] = 2880;
1408 cap[1] = 0x200;
wdenkaffae2b2002-08-17 09:36:01 +00001409 }
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001410 USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
1411 cap[1]);
wdenkaffae2b2002-08-17 09:36:01 +00001412#if 0
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001413 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
1414 cap[0] >>= 16;
wdenkaffae2b2002-08-17 09:36:01 +00001415#endif
Christian Eggersc9182612008-05-21 22:12:00 +02001416 cap[0] = cpu_to_be32(cap[0]);
1417 cap[1] = cpu_to_be32(cap[1]);
1418
wdenk149dded2003-09-10 18:20:28 +00001419 /* this assumes bigendian! */
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001420 cap[0] += 1;
1421 capacity = &cap[0];
1422 blksz = &cap[1];
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001423 USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
1424 *capacity, *blksz);
Wolfgang Denk9c998aa2005-07-21 11:57:57 +02001425 dev_desc->lba = *capacity;
1426 dev_desc->blksz = *blksz;
1427 dev_desc->type = perq;
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001428 USB_STOR_PRINTF(" address %d\n", dev_desc->target);
1429 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001430
1431 init_part(dev_desc);
1432
Michael Trimarchia0cb3fc2008-12-10 15:52:06 +01001433 USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
wdenkaffae2b2002-08-17 09:36:01 +00001434 return 1;
1435}