Blame view

common/usb_storage.c 38.4 KB
affae2bff   wdenk   Initial revision
1
  /*
460c322f1   Wolfgang Denk   (re)enabled scsi ...
2
3
4
5
6
7
8
9
10
11
   * Most of this source has been derived from the Linux USB
   * project:
   *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
   *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
   *   (c) 1999 Michael Gee (michael@linuxspecific.com)
   *   (c) 2000 Yggdrasil Computing, Inc.
   *
   *
   * Adapted for U-Boot:
   *   (C) Copyright 2001 Denis Peter, MPL AG Switzerland
affae2bff   wdenk   Initial revision
12
   *
149dded2b   wdenk   * Add support for...
13
   * For BBB support (C) Copyright 2003
792a09eb9   Detlev Zundel   Fix e-mail addres...
14
   * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
149dded2b   wdenk   * Add support for...
15
   *
460c322f1   Wolfgang Denk   (re)enabled scsi ...
16
   * BBB support based on /sys/dev/usb/umass.c from
149dded2b   wdenk   * Add support for...
17
   * FreeBSD.
affae2bff   wdenk   Initial revision
18
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
19
   * SPDX-License-Identifier:	GPL-2.0+
affae2bff   wdenk   Initial revision
20
21
22
23
24
25
26
   */
  
  /* Note:
   * Currently only the CBI transport protocoll has been implemented, and it
   * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
   * transport protocoll may work as well.
   */
149dded2b   wdenk   * Add support for...
27
28
29
30
  /*
   * New Note:
   * Support for USB Mass Storage Devices (BBB) has been added. It has
   * only been tested with USB memory sticks.
149dded2b   wdenk   * Add support for...
31
   */
affae2bff   wdenk   Initial revision
32

affae2bff   wdenk   Initial revision
33
34
  #include <common.h>
  #include <command.h>
c918261c6   Christian Eggers   USB: replace old ...
35
  #include <asm/byteorder.h>
affae2bff   wdenk   Initial revision
36
  #include <asm/processor.h>
735dd97b1   Grant Likely   [PATCH 1_4] Merge...
37
  #include <part.h>
affae2bff   wdenk   Initial revision
38
  #include <usb.h>
80885a9d5   wdenk   * Patch by Markus...
39
40
  #undef BBB_COMDAT_TRACE
  #undef BBB_XPORT_TRACE
affae2bff   wdenk   Initial revision
41

affae2bff   wdenk   Initial revision
42
43
44
45
  #include <scsi.h>
  /* direction table -- this indicates the direction of the data
   * transfer for each command code -- a 1 indicates input
   */
2ff122854   Mike Frysinger   usb_storage: cons...
46
  static const unsigned char us_direction[256/8] = {
affae2bff   wdenk   Initial revision
47
48
49
50
51
52
  	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
  	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
  #define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
f57661394   Puneet Saxena   USB: Align buffer...
53
  static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
affae2bff   wdenk   Initial revision
54
55
56
57
58
59
  
  /*
   * CBI style
   */
  
  #define US_CBI_ADSC		0
149dded2b   wdenk   * Add support for...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  /*
   * BULK only
   */
  #define US_BBB_RESET		0xff
  #define US_BBB_GET_MAX_LUN	0xfe
  
  /* Command Block Wrapper */
  typedef struct {
  	__u32		dCBWSignature;
  #	define CBWSIGNATURE	0x43425355
  	__u32		dCBWTag;
  	__u32		dCBWDataTransferLength;
  	__u8		bCBWFlags;
  #	define CBWFLAGS_OUT	0x00
  #	define CBWFLAGS_IN	0x80
  	__u8		bCBWLUN;
  	__u8		bCDBLength;
  #	define CBWCDBLENGTH	16
  	__u8		CBWCDB[CBWCDBLENGTH];
  } umass_bbb_cbw_t;
80885a9d5   wdenk   * Patch by Markus...
80
  #define UMASS_BBB_CBW_SIZE	31
a0cb3fc31   Michael Trimarchi   USB storage clean...
81
  static __u32 CBWTag;
149dded2b   wdenk   * Add support for...
82
83
84
85
86
87
88
89
90
  
  /* Command Status Wrapper */
  typedef struct {
  	__u32		dCSWSignature;
  #	define CSWSIGNATURE	0x53425355
  	__u32		dCSWTag;
  	__u32		dCSWDataResidue;
  	__u8		bCSWStatus;
  #	define CSWSTATUS_GOOD	0x0
80885a9d5   wdenk   * Patch by Markus...
91
  #	define CSWSTATUS_FAILED 0x1
149dded2b   wdenk   * Add support for...
92
93
  #	define CSWSTATUS_PHASE	0x2
  } umass_bbb_csw_t;
80885a9d5   wdenk   * Patch by Markus...
94
  #define UMASS_BBB_CSW_SIZE	13
affae2bff   wdenk   Initial revision
95
96
  
  #define USB_MAX_STOR_DEV 5
a0cb3fc31   Michael Trimarchi   USB storage clean...
97
  static int usb_max_devs; /* number of highest available usb device */
affae2bff   wdenk   Initial revision
98
99
100
101
  
  static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
  
  struct us_data;
a0cb3fc31   Michael Trimarchi   USB storage clean...
102
103
  typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
  typedef int (*trans_reset)(struct us_data *data);
affae2bff   wdenk   Initial revision
104
105
  
  struct us_data {
a0cb3fc31   Michael Trimarchi   USB storage clean...
106
107
108
  	struct usb_device *pusb_dev;	 /* this usb_device */
  
  	unsigned int	flags;			/* from filter initially */
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
109
  #	define USB_READY	(1 << 0)
a0cb3fc31   Michael Trimarchi   USB storage clean...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  	unsigned char	ifnum;			/* interface number */
  	unsigned char	ep_in;			/* in endpoint */
  	unsigned char	ep_out;			/* out ....... */
  	unsigned char	ep_int;			/* interrupt . */
  	unsigned char	subclass;		/* as in overview */
  	unsigned char	protocol;		/* .............. */
  	unsigned char	attention_done;		/* force attn on first cmd */
  	unsigned short	ip_data;		/* interrupt data */
  	int		action;			/* what to do */
  	int		ip_wanted;		/* needed */
  	int		*irq_handle;		/* for USB int requests */
  	unsigned int	irqpipe;	 	/* pipe for release_irq */
  	unsigned char	irqmaxp;		/* max packed for irq Pipe */
  	unsigned char	irqinterval;		/* Intervall for IRQ Pipe */
  	ccb		*srb;			/* current srb */
  	trans_reset	transport_reset;	/* reset routine */
  	trans_cmnd	transport;		/* transport routine */
affae2bff   wdenk   Initial revision
127
  };
cffcc5035   Benoît Thébaudeau   usb_storage: Rest...
128
  #ifdef CONFIG_USB_EHCI
1b4bd0e66   Stefan Herbrechtsmeier   usb_storage: fix ...
129
  /*
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
130
131
132
   * The U-Boot EHCI driver can handle any transfer length as long as there is
   * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
   * limited to 65535 blocks.
1b4bd0e66   Stefan Herbrechtsmeier   usb_storage: fix ...
133
   */
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
134
  #define USB_MAX_XFER_BLK	65535
cffcc5035   Benoît Thébaudeau   usb_storage: Rest...
135
  #else
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
136
  #define USB_MAX_XFER_BLK	20
cffcc5035   Benoît Thébaudeau   usb_storage: Rest...
137
  #endif
1b4bd0e66   Stefan Herbrechtsmeier   usb_storage: fix ...
138

affae2bff   wdenk   Initial revision
139
  static struct us_data usb_stor[USB_MAX_STOR_DEV];
80885a9d5   wdenk   * Patch by Markus...
140
  #define USB_STOR_TRANSPORT_GOOD	   0
affae2bff   wdenk   Initial revision
141
142
  #define USB_STOR_TRANSPORT_FAILED -1
  #define USB_STOR_TRANSPORT_ERROR  -2
a0cb3fc31   Michael Trimarchi   USB storage clean...
143
144
145
146
  int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
  		      block_dev_desc_t *dev_desc);
  int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
  		      struct us_data *ss);
ff8fef566   Sascha Silbe   Fix block device ...
147
  unsigned long usb_stor_read(int device, lbaint_t blknr,
e81e79ede   Gabe Black   usb: Support the ...
148
  			    lbaint_t blkcnt, void *buffer);
ff8fef566   Sascha Silbe   Fix block device ...
149
  unsigned long usb_stor_write(int device, lbaint_t blknr,
e81e79ede   Gabe Black   usb: Support the ...
150
  			     lbaint_t blkcnt, const void *buffer);
affae2bff   wdenk   Initial revision
151
152
  struct usb_device * usb_get_dev_index(int index);
  void uhci_show_temp_int_td(void);
df3fc5260   Matthew McClintock   disk/part.c: Make...
153
  #ifdef CONFIG_PARTITIONS
affae2bff   wdenk   Initial revision
154
155
  block_dev_desc_t *usb_stor_get_dev(int index)
  {
aaad108b8   Kim B. Heino   USB storage count
156
  	return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
affae2bff   wdenk   Initial revision
157
  }
df3fc5260   Matthew McClintock   disk/part.c: Make...
158
  #endif
affae2bff   wdenk   Initial revision
159

199adb601   Kim Phillips   common/misc: spar...
160
  static void usb_show_progress(void)
affae2bff   wdenk   Initial revision
161
  {
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
162
  	debug(".");
affae2bff   wdenk   Initial revision
163
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
164
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
165
166
167
   * show info on storage devices; 'usb start/init' must be invoked earlier
   * as we only retrieve structures populated during devices initialization
   */
f6b44e0e4   Aras Vaichas   USB Storage, add ...
168
  int usb_stor_info(void)
9c998aa83   Wolfgang Denk   Fix low-level OHC...
169
170
  {
  	int i;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
171
  	if (usb_max_devs > 0) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
172
  		for (i = 0; i < usb_max_devs; i++) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
173
  			printf("  Device %d: ", i);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
174
175
  			dev_print(&usb_dev_desc[i]);
  		}
b9e749e95   Markus Klotzbuecher   USB, Storage: fix...
176
  		return 0;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
177
  	}
1aeed8d71   Wolfgang Denk   Coding Style clea...
178

b9e749e95   Markus Klotzbuecher   USB, Storage: fix...
179
180
181
  	printf("No storage devices, perhaps not 'usb start'ed..?
  ");
  	return 1;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
182
  }
99e9ed1f4   Ludovic Courtès   usb: Add support ...
183
184
185
  static unsigned int usb_get_max_lun(struct us_data *us)
  {
  	int len;
f57661394   Puneet Saxena   USB: Align buffer...
186
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
99e9ed1f4   Ludovic Courtès   usb: Add support ...
187
188
189
190
191
  	len = usb_control_msg(us->pusb_dev,
  			      usb_rcvctrlpipe(us->pusb_dev, 0),
  			      US_BBB_GET_MAX_LUN,
  			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
  			      0, us->ifnum,
f57661394   Puneet Saxena   USB: Align buffer...
192
  			      result, sizeof(char),
99e9ed1f4   Ludovic Courtès   usb: Add support ...
193
  			      USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
194
195
  	debug("Get Max LUN -> len = %i, result = %i
  ", len, (int) *result);
f57661394   Puneet Saxena   USB: Align buffer...
196
  	return (len > 0) ? *result : 0;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
197
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
198
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
199
   * scan the usb and reports device info
affae2bff   wdenk   Initial revision
200
201
202
203
204
205
206
   * to the user if mode = 1
   * returns current device or -1 if no
   */
  int usb_stor_scan(int mode)
  {
  	unsigned char i;
  	struct usb_device *dev;
a0cb3fc31   Michael Trimarchi   USB storage clean...
207
  	if (mode == 1)
93c2582fe   Lucas Stach   usb: add support ...
208
  		printf("       scanning usb for storage devices... ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
209

affae2bff   wdenk   Initial revision
210
  	usb_disable_asynch(1); /* asynch transfer not allowed */
a0cb3fc31   Michael Trimarchi   USB storage clean...
211
212
  	for (i = 0; i < USB_MAX_STOR_DEV; i++) {
  		memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
a0cb3fc31   Michael Trimarchi   USB storage clean...
213
214
215
  		usb_dev_desc[i].if_type = IF_TYPE_USB;
  		usb_dev_desc[i].dev = i;
  		usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
a17c548b5   Wolfgang Denk   usb_storage.c: in...
216
217
  		usb_dev_desc[i].target = 0xff;
  		usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
a0cb3fc31   Michael Trimarchi   USB storage clean...
218
  		usb_dev_desc[i].block_read = usb_stor_read;
127e10842   Mahavir Jain   usb: write comman...
219
  		usb_dev_desc[i].block_write = usb_stor_write;
affae2bff   wdenk   Initial revision
220
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
221

a0cb3fc31   Michael Trimarchi   USB storage clean...
222
223
224
  	usb_max_devs = 0;
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
  		dev = usb_get_dev_index(i); /* get device */
ceb4972a8   Vivek Gautam   usb: common: Weed...
225
226
  		debug("i=%d
  ", i);
a0cb3fc31   Michael Trimarchi   USB storage clean...
227
  		if (dev == NULL)
6052cbab4   Loïc Minier   Fix misc spelling...
228
  			break; /* no more devices available */
a0cb3fc31   Michael Trimarchi   USB storage clean...
229
230
  
  		if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
99e9ed1f4   Ludovic Courtès   usb: Add support ...
231
232
  			/* OK, it's a storage device.  Iterate over its LUNs
  			 * and populate `usb_dev_desc'.
a0cb3fc31   Michael Trimarchi   USB storage clean...
233
  			 */
99e9ed1f4   Ludovic Courtès   usb: Add support ...
234
235
236
237
238
239
240
241
  			int lun, max_lun, start = usb_max_devs;
  
  			max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
  			for (lun = 0;
  			     lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
  			     lun++) {
  				usb_dev_desc[usb_max_devs].lun = lun;
  				if (usb_stor_get_info(dev, &usb_stor[start],
605bd75af   Vivek Gautam   USB: Some cleanup...
242
243
244
  				    &usb_dev_desc[usb_max_devs]) == 1) {
  					usb_max_devs++;
  				}
99e9ed1f4   Ludovic Courtès   usb: Add support ...
245
246
  			}
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
247
248
249
250
251
  		/* if storage device */
  		if (usb_max_devs == USB_MAX_STOR_DEV) {
  			printf("max USB Storage Device reached: %d stopping
  ",
  				usb_max_devs);
affae2bff   wdenk   Initial revision
252
253
254
  			break;
  		}
  	} /* for */
095b8a379   Wolfgang Denk   Coding style cleanup
255

affae2bff   wdenk   Initial revision
256
  	usb_disable_asynch(0); /* asynch transfer allowed */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
257
258
  	printf("%d Storage Device(s) found
  ", usb_max_devs);
a0cb3fc31   Michael Trimarchi   USB storage clean...
259
  	if (usb_max_devs > 0)
affae2bff   wdenk   Initial revision
260
  		return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
261
  	return -1;
affae2bff   wdenk   Initial revision
262
263
264
265
266
  }
  
  static int usb_stor_irq(struct usb_device *dev)
  {
  	struct us_data *us;
a0cb3fc31   Michael Trimarchi   USB storage clean...
267
  	us = (struct us_data *)dev->privptr;
affae2bff   wdenk   Initial revision
268

a0cb3fc31   Michael Trimarchi   USB storage clean...
269
270
  	if (us->ip_wanted)
  		us->ip_wanted = 0;
affae2bff   wdenk   Initial revision
271
272
  	return 0;
  }
ceb4972a8   Vivek Gautam   usb: common: Weed...
273
  #ifdef	DEBUG
affae2bff   wdenk   Initial revision
274

a0cb3fc31   Michael Trimarchi   USB storage clean...
275
  static void usb_show_srb(ccb *pccb)
affae2bff   wdenk   Initial revision
276
277
  {
  	int i;
a0cb3fc31   Michael Trimarchi   USB storage clean...
278
279
280
281
  	printf("SRB: len %d datalen 0x%lX
   ", pccb->cmdlen, pccb->datalen);
  	for (i = 0; i < 12; i++)
  		printf("%02X ", pccb->cmd[i]);
affae2bff   wdenk   Initial revision
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  	printf("
  ");
  }
  
  static void display_int_status(unsigned long tmp)
  {
  	printf("Status: %s %s %s %s %s %s %s
  ",
  		(tmp & USB_ST_ACTIVE) ? "Active" : "",
  		(tmp & USB_ST_STALLED) ? "Stalled" : "",
  		(tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
  		(tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
  		(tmp & USB_ST_NAK_REC) ? "NAKed" : "",
  		(tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
  		(tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
  }
  #endif
  /***********************************************************************
   * Data transfer routines
   ***********************************************************************/
  
  static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
  {
  	int max_size;
  	int this_xfer;
  	int result;
  	int partial;
  	int maxtry;
  	int stat;
  
  	/* determine the maximum packet size for these transfers */
  	max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
  
  	/* while we have data left to transfer */
  	while (length) {
  
  		/* calculate how long this will be -- maximum or a remainder */
  		this_xfer = length > max_size ? max_size : length;
  		length -= this_xfer;
  
  		/* setup the retry counter */
  		maxtry = 10;
  
  		/* set up the transfer loop */
  		do {
  			/* transfer the data */
ceb4972a8   Vivek Gautam   usb: common: Weed...
328
329
330
  			debug("Bulk xfer 0x%x(%d) try #%d
  ",
  			      (unsigned int)buf, this_xfer, 11 - maxtry);
affae2bff   wdenk   Initial revision
331
  			result = usb_bulk_msg(us->pusb_dev, pipe, buf,
a0cb3fc31   Michael Trimarchi   USB storage clean...
332
333
  					      this_xfer, &partial,
  					      USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
334
335
336
  			debug("bulk_msg returned %d xferred %d/%d
  ",
  			      result, partial, this_xfer);
a0cb3fc31   Michael Trimarchi   USB storage clean...
337
338
339
340
  			if (us->pusb_dev->status != 0) {
  				/* if we stall, we need to clear it before
  				 * we go on
  				 */
ceb4972a8   Vivek Gautam   usb: common: Weed...
341
  #ifdef DEBUG
affae2bff   wdenk   Initial revision
342
343
344
  				display_int_status(us->pusb_dev->status);
  #endif
  				if (us->pusb_dev->status & USB_ST_STALLED) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
345
346
347
  					debug("stalled ->clearing endpoint" \
  					      "halt for pipe 0x%x
  ", pipe);
affae2bff   wdenk   Initial revision
348
349
  					stat = us->pusb_dev->status;
  					usb_clear_halt(us->pusb_dev, pipe);
a0cb3fc31   Michael Trimarchi   USB storage clean...
350
351
  					us->pusb_dev->status = stat;
  					if (this_xfer == partial) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
352
353
354
355
356
  						debug("bulk transferred" \
  						      "with error %lX," \
  						      " but data ok
  ",
  						      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
357
358
359
360
361
362
  						return 0;
  					}
  					else
  						return result;
  				}
  				if (us->pusb_dev->status & USB_ST_NAK_REC) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
363
364
  					debug("Device NAKed bulk_msg
  ");
affae2bff   wdenk   Initial revision
365
366
  					return result;
  				}
ceb4972a8   Vivek Gautam   usb: common: Weed...
367
  				debug("bulk transferred with error");
a0cb3fc31   Michael Trimarchi   USB storage clean...
368
  				if (this_xfer == partial) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
369
370
371
  					debug(" %ld, but data ok
  ",
  					      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
372
373
374
  					return 0;
  				}
  				/* if our try counter reaches 0, bail out */
ceb4972a8   Vivek Gautam   usb: common: Weed...
375
376
377
  					debug(" %ld, data %d
  ",
  					      us->pusb_dev->status, partial);
affae2bff   wdenk   Initial revision
378
379
380
381
382
383
384
  				if (!maxtry--)
  						return result;
  			}
  			/* update to show what data was transferred */
  			this_xfer -= partial;
  			buf += partial;
  			/* continue until this transfer is done */
a0cb3fc31   Michael Trimarchi   USB storage clean...
385
  		} while (this_xfer);
affae2bff   wdenk   Initial revision
386
387
388
389
390
  	}
  
  	/* if we get here, we're done and successful */
  	return 0;
  }
149dded2b   wdenk   * Add support for...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  static int usb_stor_BBB_reset(struct us_data *us)
  {
  	int result;
  	unsigned int pipe;
  
  	/*
  	 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
  	 *
  	 * For Reset Recovery the host shall issue in the following order:
  	 * a) a Bulk-Only Mass Storage Reset
  	 * b) a Clear Feature HALT to the Bulk-In endpoint
  	 * c) a Clear Feature HALT to the Bulk-Out endpoint
  	 *
  	 * This is done in 3 steps.
  	 *
  	 * If the reset doesn't succeed, the device should be port reset.
  	 *
  	 * This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
  	 */
ceb4972a8   Vivek Gautam   usb: common: Weed...
410
411
  	debug("BBB_reset
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
412
413
414
  	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
  				 US_BBB_RESET,
  				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
199adb601   Kim Phillips   common/misc: spar...
415
  				 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
416

a0cb3fc31   Michael Trimarchi   USB storage clean...
417
  	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
418
419
  		debug("RESET:stall
  ");
149dded2b   wdenk   * Add support for...
420
421
  		return -1;
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
422

149dded2b   wdenk   * Add support for...
423
  	/* long wait for reset */
5b84dd67c   Mike Frysinger   usb: replace wait...
424
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
425
426
427
  	debug("BBB_reset result %d: status %lX reset
  ",
  	      result, us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
428
429
430
  	pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
  	result = usb_clear_halt(us->pusb_dev, pipe);
  	/* long wait for reset */
5b84dd67c   Mike Frysinger   usb: replace wait...
431
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
432
433
434
  	debug("BBB_reset result %d: status %lX clearing IN endpoint
  ",
  	      result, us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
435
436
437
  	/* long wait for reset */
  	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
  	result = usb_clear_halt(us->pusb_dev, pipe);
5b84dd67c   Mike Frysinger   usb: replace wait...
438
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
439
440
441
442
443
  	debug("BBB_reset result %d: status %lX clearing OUT endpoint
  ",
  	      result, us->pusb_dev->status);
  	debug("BBB_reset done
  ");
149dded2b   wdenk   * Add support for...
444
445
  	return 0;
  }
affae2bff   wdenk   Initial revision
446
447
448
449
450
451
452
453
  /* FIXME: this reset function doesn't really reset the port, and it
   * should. Actually it should probably do what it's doing here, and
   * reset the port physically
   */
  static int usb_stor_CB_reset(struct us_data *us)
  {
  	unsigned char cmd[12];
  	int result;
ceb4972a8   Vivek Gautam   usb: common: Weed...
454
455
  	debug("CB_reset
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
456
  	memset(cmd, 0xff, sizeof(cmd));
affae2bff   wdenk   Initial revision
457
458
  	cmd[0] = SCSI_SEND_DIAG;
  	cmd[1] = 4;
a0cb3fc31   Michael Trimarchi   USB storage clean...
459
460
461
462
463
  	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
  				 US_CBI_ADSC,
  				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  				 0, us->ifnum, cmd, sizeof(cmd),
  				 USB_CNTL_TIMEOUT * 5);
affae2bff   wdenk   Initial revision
464
465
  
  	/* long wait for reset */
5b84dd67c   Mike Frysinger   usb: replace wait...
466
  	mdelay(1500);
ceb4972a8   Vivek Gautam   usb: common: Weed...
467
468
469
  	debug("CB_reset result %d: status %lX clearing endpoint halt
  ",
  	      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
470
471
  	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
  	usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
ceb4972a8   Vivek Gautam   usb: common: Weed...
472
473
  	debug("CB_reset done
  ");
affae2bff   wdenk   Initial revision
474
475
  	return 0;
  }
149dded2b   wdenk   * Add support for...
476
477
478
479
  /*
   * Set up the command for a BBB device. Note that the actual SCSI
   * command is copied into cbw.CBWCDB.
   */
199adb601   Kim Phillips   common/misc: spar...
480
  static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
149dded2b   wdenk   * Add support for...
481
482
483
484
485
  {
  	int result;
  	int actlen;
  	int dir_in;
  	unsigned int pipe;
f57661394   Puneet Saxena   USB: Align buffer...
486
  	ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
149dded2b   wdenk   * Add support for...
487
488
489
490
  
  	dir_in = US_DIRECTION(srb->cmd[0]);
  
  #ifdef BBB_COMDAT_TRACE
605bd75af   Vivek Gautam   USB: Some cleanup...
491
492
  	printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p
  ",
a0cb3fc31   Michael Trimarchi   USB storage clean...
493
494
  		dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
  		srb->pdata);
149dded2b   wdenk   * Add support for...
495
  	if (srb->cmdlen) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
496
  		for (result = 0; result < srb->cmdlen; result++)
149dded2b   wdenk   * Add support for...
497
498
499
500
501
502
503
  			printf("cmd[%d] %#x ", result, srb->cmd[result]);
  		printf("
  ");
  	}
  #endif
  	/* sanity checks */
  	if (!(srb->cmdlen <= CBWCDBLENGTH)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
504
505
  		debug("usb_stor_BBB_comdat:cmdlen too large
  ");
149dded2b   wdenk   * Add support for...
506
507
508
509
510
  		return -1;
  	}
  
  	/* always OUT to the ep */
  	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
f57661394   Puneet Saxena   USB: Align buffer...
511
512
513
514
515
516
  	cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
  	cbw->dCBWTag = cpu_to_le32(CBWTag++);
  	cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
  	cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
  	cbw->bCBWLUN = srb->lun;
  	cbw->bCDBLength = srb->cmdlen;
149dded2b   wdenk   * Add support for...
517
518
  	/* copy the command data into the CBW command data buffer */
  	/* DST SRC LEN!!! */
f57661394   Puneet Saxena   USB: Align buffer...
519
520
  	memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
  	result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
a0cb3fc31   Michael Trimarchi   USB storage clean...
521
  			      &actlen, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
522
  	if (result < 0)
ceb4972a8   Vivek Gautam   usb: common: Weed...
523
524
  		debug("usb_stor_BBB_comdat:usb_bulk_msg error
  ");
149dded2b   wdenk   * Add support for...
525
526
  	return result;
  }
affae2bff   wdenk   Initial revision
527
528
529
  /* FIXME: we also need a CBI_command which sets up the completion
   * interrupt, and waits for it
   */
199adb601   Kim Phillips   common/misc: spar...
530
  static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
531
  {
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
532
  	int result = 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
533
  	int dir_in, retry;
affae2bff   wdenk   Initial revision
534
535
  	unsigned int pipe;
  	unsigned long status;
a0cb3fc31   Michael Trimarchi   USB storage clean...
536
537
  	retry = 5;
  	dir_in = US_DIRECTION(srb->cmd[0]);
affae2bff   wdenk   Initial revision
538

a0cb3fc31   Michael Trimarchi   USB storage clean...
539
540
541
542
543
544
  	if (dir_in)
  		pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
  	else
  		pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
  
  	while (retry--) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
545
546
547
  		debug("CBI gets a command: Try %d
  ", 5 - retry);
  #ifdef DEBUG
affae2bff   wdenk   Initial revision
548
549
550
  		usb_show_srb(srb);
  #endif
  		/* let's send the command via the control pipe */
a0cb3fc31   Michael Trimarchi   USB storage clean...
551
552
553
554
  		result = usb_control_msg(us->pusb_dev,
  					 usb_sndctrlpipe(us->pusb_dev , 0),
  					 US_CBI_ADSC,
  					 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
affae2bff   wdenk   Initial revision
555
  					 0, us->ifnum,
a0cb3fc31   Michael Trimarchi   USB storage clean...
556
557
  					 srb->cmd, srb->cmdlen,
  					 USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
558
559
560
  		debug("CB_transport: control msg returned %d, status %lX
  ",
  		      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
561
562
  		/* check the return code for the command */
  		if (result < 0) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
563
564
  			if (us->pusb_dev->status & USB_ST_STALLED) {
  				status = us->pusb_dev->status;
ceb4972a8   Vivek Gautam   usb: common: Weed...
565
566
567
  				debug(" stall during command found," \
  				      " clear pipe
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
568
569
570
  				usb_clear_halt(us->pusb_dev,
  					      usb_sndctrlpipe(us->pusb_dev, 0));
  				us->pusb_dev->status = status;
affae2bff   wdenk   Initial revision
571
  			}
ceb4972a8   Vivek Gautam   usb: common: Weed...
572
573
574
575
  			debug(" error during command %02X" \
  			      " Stat = %lX
  ", srb->cmd[0],
  			      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
576
577
578
  			return result;
  		}
  		/* transfer the data payload for this command, if one exists*/
ceb4972a8   Vivek Gautam   usb: common: Weed...
579
580
581
582
  		debug("CB_transport: control msg returned %d," \
  		      " direction is %s to go 0x%lx
  ", result,
  		      dir_in ? "IN" : "OUT", srb->datalen);
affae2bff   wdenk   Initial revision
583
  		if (srb->datalen) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
584
585
  			result = us_one_transfer(us, pipe, (char *)srb->pdata,
  						 srb->datalen);
ceb4972a8   Vivek Gautam   usb: common: Weed...
586
587
588
589
590
  			debug("CBI attempted to transfer data," \
  			      " result is %d status %lX, len %d
  ",
  			      result, us->pusb_dev->status,
  				us->pusb_dev->act_len);
a0cb3fc31   Michael Trimarchi   USB storage clean...
591
  			if (!(us->pusb_dev->status & USB_ST_NAK_REC))
affae2bff   wdenk   Initial revision
592
593
594
595
596
597
598
599
600
  				break;
  		} /* if (srb->datalen) */
  		else
  			break;
  	}
  	/* return result */
  
  	return result;
  }
199adb601   Kim Phillips   common/misc: spar...
601
  static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
602
603
  {
  	int timeout;
80885a9d5   wdenk   * Patch by Markus...
604
  	us->ip_wanted = 1;
a0cb3fc31   Michael Trimarchi   USB storage clean...
605
  	submit_int_msg(us->pusb_dev, us->irqpipe,
80885a9d5   wdenk   * Patch by Markus...
606
607
608
  			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
  	timeout = 1000;
  	while (timeout--) {
199adb601   Kim Phillips   common/misc: spar...
609
  		if ((volatile int *) us->ip_wanted == NULL)
affae2bff   wdenk   Initial revision
610
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
611
  		mdelay(10);
affae2bff   wdenk   Initial revision
612
613
  	}
  	if (us->ip_wanted) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
614
615
  		printf("	Did not get interrupt on CBI
  ");
affae2bff   wdenk   Initial revision
616
617
618
  		us->ip_wanted = 0;
  		return USB_STOR_TRANSPORT_ERROR;
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
619
620
621
622
  	debug("Got interrupt data 0x%x, transfered %d status 0x%lX
  ",
  	      us->ip_data, us->pusb_dev->irq_act_len,
  	      us->pusb_dev->irq_status);
affae2bff   wdenk   Initial revision
623
624
625
626
627
  	/* UFI gives us ASC and ASCQ, like a request sense */
  	if (us->subclass == US_SC_UFI) {
  		if (srb->cmd[0] == SCSI_REQ_SENSE ||
  		    srb->cmd[0] == SCSI_INQUIRY)
  			return USB_STOR_TRANSPORT_GOOD; /* Good */
80885a9d5   wdenk   * Patch by Markus...
628
629
  		else if (us->ip_data)
  			return USB_STOR_TRANSPORT_FAILED;
affae2bff   wdenk   Initial revision
630
  		else
80885a9d5   wdenk   * Patch by Markus...
631
  			return USB_STOR_TRANSPORT_GOOD;
affae2bff   wdenk   Initial revision
632
633
634
  	}
  	/* otherwise, we interpret the data normally */
  	switch (us->ip_data) {
80885a9d5   wdenk   * Patch by Markus...
635
636
637
638
639
640
641
  	case 0x0001:
  		return USB_STOR_TRANSPORT_GOOD;
  	case 0x0002:
  		return USB_STOR_TRANSPORT_FAILED;
  	default:
  		return USB_STOR_TRANSPORT_ERROR;
  	}			/* switch */
affae2bff   wdenk   Initial revision
642
643
644
645
646
  	return USB_STOR_TRANSPORT_ERROR;
  }
  
  #define USB_TRANSPORT_UNKNOWN_RETRY 5
  #define USB_TRANSPORT_NOT_READY_RETRY 10
149dded2b   wdenk   * Add support for...
647
  /* clear a stall on an endpoint - special for BBB devices */
199adb601   Kim Phillips   common/misc: spar...
648
  static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
149dded2b   wdenk   * Add support for...
649
650
651
652
  {
  	int result;
  
  	/* ENDPOINT_HALT = 0, so set value to 0 */
a0cb3fc31   Michael Trimarchi   USB storage clean...
653
  	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
149dded2b   wdenk   * Add support for...
654
  				USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
199adb601   Kim Phillips   common/misc: spar...
655
  				0, endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
656
657
  	return result;
  }
199adb601   Kim Phillips   common/misc: spar...
658
  static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
149dded2b   wdenk   * Add support for...
659
660
661
662
663
  {
  	int result, retry;
  	int dir_in;
  	int actlen, data_actlen;
  	unsigned int pipe, pipein, pipeout;
f57661394   Puneet Saxena   USB: Align buffer...
664
  	ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
149dded2b   wdenk   * Add support for...
665
666
667
668
669
670
671
672
  #ifdef BBB_XPORT_TRACE
  	unsigned char *ptr;
  	int index;
  #endif
  
  	dir_in = US_DIRECTION(srb->cmd[0]);
  
  	/* COMMAND phase */
ceb4972a8   Vivek Gautam   usb: common: Weed...
673
674
  	debug("COMMAND phase
  ");
149dded2b   wdenk   * Add support for...
675
676
  	result = usb_stor_BBB_comdat(srb, us);
  	if (result < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
677
678
679
  		debug("failed to send CBW status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
680
681
682
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	}
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
683
684
  	if (!(us->flags & USB_READY))
  		mdelay(5);
149dded2b   wdenk   * Add support for...
685
686
687
  	pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
  	pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
  	/* DATA phase + error handling */
149dded2b   wdenk   * Add support for...
688
689
690
691
  	data_actlen = 0;
  	/* no data, go immediately to the STATUS phase */
  	if (srb->datalen == 0)
  		goto st;
ceb4972a8   Vivek Gautam   usb: common: Weed...
692
693
  	debug("DATA phase
  ");
149dded2b   wdenk   * Add support for...
694
695
696
697
  	if (dir_in)
  		pipe = pipein;
  	else
  		pipe = pipeout;
a0cb3fc31   Michael Trimarchi   USB storage clean...
698
699
  	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
  			      &data_actlen, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
700
  	/* special handling of STALL in DATA phase */
a0cb3fc31   Michael Trimarchi   USB storage clean...
701
  	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
702
703
  		debug("DATA:stall
  ");
149dded2b   wdenk   * Add support for...
704
  		/* clear the STALL on the endpoint */
a0cb3fc31   Michael Trimarchi   USB storage clean...
705
706
  		result = usb_stor_BBB_clear_endpt_stall(us,
  					dir_in ? us->ep_in : us->ep_out);
149dded2b   wdenk   * Add support for...
707
708
709
710
711
  		if (result >= 0)
  			/* continue on to STATUS phase */
  			goto st;
  	}
  	if (result < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
712
713
714
  		debug("usb_bulk_msg error status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
715
716
717
718
719
720
721
722
723
724
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	}
  #ifdef BBB_XPORT_TRACE
  	for (index = 0; index < data_actlen; index++)
  		printf("pdata[%d] %#x ", index, srb->pdata[index]);
  	printf("
  ");
  #endif
  	/* STATUS phase + error handling */
a0cb3fc31   Michael Trimarchi   USB storage clean...
725
  st:
149dded2b   wdenk   * Add support for...
726
  	retry = 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
727
  again:
ceb4972a8   Vivek Gautam   usb: common: Weed...
728
729
  	debug("STATUS phase
  ");
f57661394   Puneet Saxena   USB: Align buffer...
730
  	result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
9c998aa83   Wolfgang Denk   Fix low-level OHC...
731
  				&actlen, USB_CNTL_TIMEOUT*5);
149dded2b   wdenk   * Add support for...
732
  	/* special handling of STALL in STATUS phase */
a0cb3fc31   Michael Trimarchi   USB storage clean...
733
734
  	if ((result < 0) && (retry < 1) &&
  	    (us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
735
736
  		debug("STATUS:stall
  ");
149dded2b   wdenk   * Add support for...
737
738
739
740
741
742
743
  		/* clear the STALL on the endpoint */
  		result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
  		if (result >= 0 && (retry++ < 1))
  			/* do a retry */
  			goto again;
  	}
  	if (result < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
744
745
746
  		debug("usb_bulk_msg error status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
747
748
749
750
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	}
  #ifdef BBB_XPORT_TRACE
f57661394   Puneet Saxena   USB: Align buffer...
751
  	ptr = (unsigned char *)csw;
149dded2b   wdenk   * Add support for...
752
753
754
755
756
757
  	for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
  		printf("ptr[%d] %#x ", index, ptr[index]);
  	printf("
  ");
  #endif
  	/* misuse pipe to get the residue */
f57661394   Puneet Saxena   USB: Align buffer...
758
  	pipe = le32_to_cpu(csw->dCSWDataResidue);
149dded2b   wdenk   * Add support for...
759
760
  	if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
  		pipe = srb->datalen - data_actlen;
f57661394   Puneet Saxena   USB: Align buffer...
761
  	if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
762
763
  		debug("!CSWSIGNATURE
  ");
149dded2b   wdenk   * Add support for...
764
765
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
766
  	} else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
767
768
  		debug("!Tag
  ");
149dded2b   wdenk   * Add support for...
769
770
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
771
  	} else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
772
773
  		debug(">PHASE
  ");
149dded2b   wdenk   * Add support for...
774
775
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
776
  	} else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
777
778
  		debug("=PHASE
  ");
149dded2b   wdenk   * Add support for...
779
780
781
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	} else if (data_actlen > srb->datalen) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
782
783
784
  		debug("transferred %dB instead of %ldB
  ",
  		      data_actlen, srb->datalen);
149dded2b   wdenk   * Add support for...
785
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
786
  	} else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
787
788
  		debug("FAILED
  ");
149dded2b   wdenk   * Add support for...
789
790
791
792
793
  		return USB_STOR_TRANSPORT_FAILED;
  	}
  
  	return result;
  }
199adb601   Kim Phillips   common/misc: spar...
794
  static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
795
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
796
  	int result, status;
affae2bff   wdenk   Initial revision
797
798
  	ccb *psrb;
  	ccb reqsrb;
a0cb3fc31   Michael Trimarchi   USB storage clean...
799
  	int retry, notready;
affae2bff   wdenk   Initial revision
800

d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
801
  	psrb = &reqsrb;
a0cb3fc31   Michael Trimarchi   USB storage clean...
802
803
804
  	status = USB_STOR_TRANSPORT_GOOD;
  	retry = 0;
  	notready = 0;
affae2bff   wdenk   Initial revision
805
806
  	/* issue the command */
  do_retry:
a0cb3fc31   Michael Trimarchi   USB storage clean...
807
  	result = usb_stor_CB_comdat(srb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
808
809
810
  	debug("command / Data returned %d, status %lX
  ",
  	      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
811
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
812
813
  	if (us->protocol == US_PR_CBI) {
  		status = usb_stor_CBI_get_status(srb, us);
affae2bff   wdenk   Initial revision
814
  		/* if the status is error, report it */
a0cb3fc31   Michael Trimarchi   USB storage clean...
815
  		if (status == USB_STOR_TRANSPORT_ERROR) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
816
817
  			debug(" USB CBI Command Error
  ");
affae2bff   wdenk   Initial revision
818
819
  			return status;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
820
821
822
823
824
  		srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
  		srb->sense_buf[13] = (unsigned char)(us->ip_data & 0xff);
  		if (!us->ip_data) {
  			/* if the status is good, report it */
  			if (status == USB_STOR_TRANSPORT_GOOD) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
825
826
  				debug(" USB CBI Command Good
  ");
affae2bff   wdenk   Initial revision
827
828
829
830
831
832
  				return status;
  			}
  		}
  	}
  	/* do we have to issue an auto request? */
  	/* HERE we have to check the result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
833
  	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
834
835
  		debug("ERROR %lX
  ", us->pusb_dev->status);
affae2bff   wdenk   Initial revision
836
837
838
  		us->transport_reset(us);
  		return USB_STOR_TRANSPORT_ERROR;
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
839
840
841
842
  	if ((us->protocol == US_PR_CBI) &&
  	    ((srb->cmd[0] == SCSI_REQ_SENSE) ||
  	    (srb->cmd[0] == SCSI_INQUIRY))) {
  		/* do not issue an autorequest after request sense */
ceb4972a8   Vivek Gautam   usb: common: Weed...
843
844
  		debug("No auto request and good
  ");
affae2bff   wdenk   Initial revision
845
846
847
  		return USB_STOR_TRANSPORT_GOOD;
  	}
  	/* issue an request_sense */
a0cb3fc31   Michael Trimarchi   USB storage clean...
848
849
850
851
852
  	memset(&psrb->cmd[0], 0, 12);
  	psrb->cmd[0] = SCSI_REQ_SENSE;
  	psrb->cmd[1] = srb->lun << 5;
  	psrb->cmd[4] = 18;
  	psrb->datalen = 18;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
853
  	psrb->pdata = &srb->sense_buf[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
854
  	psrb->cmdlen = 12;
affae2bff   wdenk   Initial revision
855
  	/* issue the command */
a0cb3fc31   Michael Trimarchi   USB storage clean...
856
  	result = usb_stor_CB_comdat(psrb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
857
858
  	debug("auto request returned %d
  ", result);
affae2bff   wdenk   Initial revision
859
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
860
861
862
863
  	if (us->protocol == US_PR_CBI)
  		status = usb_stor_CBI_get_status(psrb, us);
  
  	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
864
865
866
  		debug(" AUTO REQUEST ERROR %ld
  ",
  		      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
867
868
  		return USB_STOR_TRANSPORT_ERROR;
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
869
870
871
872
  	debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X
  ",
  	      srb->sense_buf[0], srb->sense_buf[2],
  	      srb->sense_buf[12], srb->sense_buf[13]);
affae2bff   wdenk   Initial revision
873
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
874
875
876
877
  	if ((srb->sense_buf[2] == 0) &&
  	    (srb->sense_buf[12] == 0) &&
  	    (srb->sense_buf[13] == 0)) {
  		/* ok, no sense */
affae2bff   wdenk   Initial revision
878
  		return USB_STOR_TRANSPORT_GOOD;
a0cb3fc31   Michael Trimarchi   USB storage clean...
879
  	}
affae2bff   wdenk   Initial revision
880
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
881
882
883
  	switch (srb->sense_buf[2]) {
  	case 0x01:
  		/* Recovered Error */
149dded2b   wdenk   * Add support for...
884
  		return USB_STOR_TRANSPORT_GOOD;
80885a9d5   wdenk   * Patch by Markus...
885
  		break;
a0cb3fc31   Michael Trimarchi   USB storage clean...
886
887
888
889
890
891
892
893
  	case 0x02:
  		/* Not Ready */
  		if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
  			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
  			       " 0x%02X (NOT READY)
  ", srb->cmd[0],
  				srb->sense_buf[0], srb->sense_buf[2],
  				srb->sense_buf[12], srb->sense_buf[13]);
149dded2b   wdenk   * Add support for...
894
895
  			return USB_STOR_TRANSPORT_FAILED;
  		} else {
5b84dd67c   Mike Frysinger   usb: replace wait...
896
  			mdelay(100);
149dded2b   wdenk   * Add support for...
897
898
899
900
  			goto do_retry;
  		}
  		break;
  	default:
a0cb3fc31   Michael Trimarchi   USB storage clean...
901
902
903
904
905
906
  		if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
  			printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
  			       " 0x%02X
  ", srb->cmd[0], srb->sense_buf[0],
  				srb->sense_buf[2], srb->sense_buf[12],
  				srb->sense_buf[13]);
149dded2b   wdenk   * Add support for...
907
  			return USB_STOR_TRANSPORT_FAILED;
a0cb3fc31   Michael Trimarchi   USB storage clean...
908
  		} else
149dded2b   wdenk   * Add support for...
909
  			goto do_retry;
149dded2b   wdenk   * Add support for...
910
  		break;
affae2bff   wdenk   Initial revision
911
912
913
  	}
  	return USB_STOR_TRANSPORT_FAILED;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
914
  static int usb_inquiry(ccb *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
915
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
916
917
  	int retry, i;
  	retry = 5;
affae2bff   wdenk   Initial revision
918
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
919
920
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_INQUIRY;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
921
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
922
923
924
925
  		srb->cmd[4] = 36;
  		srb->datalen = 36;
  		srb->cmdlen = 12;
  		i = ss->transport(srb, ss);
ceb4972a8   Vivek Gautam   usb: common: Weed...
926
927
  		debug("inquiry returns %d
  ", i);
a0cb3fc31   Michael Trimarchi   USB storage clean...
928
  		if (i == 0)
affae2bff   wdenk   Initial revision
929
  			break;
fac71cc49   Kim B. Heino   USB storage probe
930
  	} while (--retry);
149dded2b   wdenk   * Add support for...
931

a0cb3fc31   Michael Trimarchi   USB storage clean...
932
  	if (!retry) {
affae2bff   wdenk   Initial revision
933
934
935
936
937
938
  		printf("error in inquiry
  ");
  		return -1;
  	}
  	return 0;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
939
  static int usb_request_sense(ccb *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
940
941
  {
  	char *ptr;
80885a9d5   wdenk   * Patch by Markus...
942

a0cb3fc31   Michael Trimarchi   USB storage clean...
943
944
945
  	ptr = (char *)srb->pdata;
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_REQ_SENSE;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
946
  	srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
947
948
  	srb->cmd[4] = 18;
  	srb->datalen = 18;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
949
  	srb->pdata = &srb->sense_buf[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
950
951
  	srb->cmdlen = 12;
  	ss->transport(srb, ss);
ceb4972a8   Vivek Gautam   usb: common: Weed...
952
953
954
955
  	debug("Request Sense returned %02X %02X %02X
  ",
  	      srb->sense_buf[2], srb->sense_buf[12],
  	      srb->sense_buf[13]);
a0cb3fc31   Michael Trimarchi   USB storage clean...
956
  	srb->pdata = (uchar *)ptr;
affae2bff   wdenk   Initial revision
957
958
  	return 0;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
959
  static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
960
  {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
961
  	int retries = 10;
149dded2b   wdenk   * Add support for...
962

affae2bff   wdenk   Initial revision
963
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
964
965
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_TST_U_RDY;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
966
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
967
968
  		srb->datalen = 0;
  		srb->cmdlen = 12;
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
969
970
  		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
  			ss->flags |= USB_READY;
affae2bff   wdenk   Initial revision
971
  			return 0;
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
972
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
973
  		usb_request_sense(srb, ss);
8b57e2f08   Vincent Palatin   usb: properly det...
974
975
976
977
978
979
980
981
982
983
  		/*
  		 * Check the Key Code Qualifier, if it matches
  		 * "Not Ready - medium not present"
  		 * (the sense Key equals 0x2 and the ASC is 0x3a)
  		 * return immediately as the medium being absent won't change
  		 * unless there is a user action.
  		 */
  		if ((srb->sense_buf[2] == 0x02) &&
  		    (srb->sense_buf[12] == 0x3a))
  			return -1;
5b84dd67c   Mike Frysinger   usb: replace wait...
984
  		mdelay(100);
a0cb3fc31   Michael Trimarchi   USB storage clean...
985
  	} while (retries--);
149dded2b   wdenk   * Add support for...
986

affae2bff   wdenk   Initial revision
987
988
  	return -1;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
989
  static int usb_read_capacity(ccb *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
990
991
  {
  	int retry;
a0cb3fc31   Michael Trimarchi   USB storage clean...
992
993
  	/* XXX retries */
  	retry = 3;
affae2bff   wdenk   Initial revision
994
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
995
996
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_RD_CAPAC;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
997
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
998
999
1000
  		srb->datalen = 8;
  		srb->cmdlen = 12;
  		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
affae2bff   wdenk   Initial revision
1001
  			return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1002
  	} while (retry--);
149dded2b   wdenk   * Add support for...
1003

affae2bff   wdenk   Initial revision
1004
1005
  	return -1;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
1006
1007
  static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
  		       unsigned short blocks)
affae2bff   wdenk   Initial revision
1008
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1009
1010
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_READ10;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1011
  	srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1012
1013
1014
1015
1016
1017
1018
  	srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
  	srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
  	srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
  	srb->cmd[5] = ((unsigned char) (start)) & 0xff;
  	srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
  	srb->cmd[8] = (unsigned char) blocks & 0xff;
  	srb->cmdlen = 12;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1019
1020
  	debug("read10: start %lx blocks %x
  ", start, blocks);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1021
  	return ss->transport(srb, ss);
affae2bff   wdenk   Initial revision
1022
  }
127e10842   Mahavir Jain   usb: write comman...
1023
1024
1025
1026
1027
  static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
  			unsigned short blocks)
  {
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_WRITE10;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1028
  	srb->cmd[1] = srb->lun << 5;
127e10842   Mahavir Jain   usb: write comman...
1029
1030
1031
1032
1033
1034
1035
  	srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
  	srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
  	srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
  	srb->cmd[5] = ((unsigned char) (start)) & 0xff;
  	srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
  	srb->cmd[8] = (unsigned char) blocks & 0xff;
  	srb->cmdlen = 12;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1036
1037
  	debug("write10: start %lx blocks %x
  ", start, blocks);
127e10842   Mahavir Jain   usb: write comman...
1038
1039
  	return ss->transport(srb, ss);
  }
affae2bff   wdenk   Initial revision
1040

ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  #ifdef CONFIG_USB_BIN_FIXUP
  /*
   * Some USB storage devices queried for SCSI identification data respond with
   * binary strings, which if output to the console freeze the terminal. The
   * workaround is to modify the vendor and product strings read from such
   * device with proper values (as reported by 'usb info').
   *
   * Vendor and product length limits are taken from the definition of
   * block_dev_desc_t in include/part.h.
   */
  static void usb_bin_fixup(struct usb_device_descriptor descriptor,
  				unsigned char vendor[],
  				unsigned char product[]) {
  	const unsigned char max_vendor_len = 40;
  	const unsigned char max_product_len = 20;
  	if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1057
1058
1059
  		strncpy((char *)vendor, "SMSC", max_vendor_len);
  		strncpy((char *)product, "Flash Media Cntrller",
  			max_product_len);
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1060
1061
1062
  	}
  }
  #endif /* CONFIG_USB_BIN_FIXUP */
ff8fef566   Sascha Silbe   Fix block device ...
1063
  unsigned long usb_stor_read(int device, lbaint_t blknr,
e81e79ede   Gabe Black   usb: Support the ...
1064
  			    lbaint_t blkcnt, void *buffer)
affae2bff   wdenk   Initial revision
1065
  {
e81e79ede   Gabe Black   usb: Support the ...
1066
1067
  	lbaint_t start, blks;
  	uintptr_t buf_addr;
affae2bff   wdenk   Initial revision
1068
1069
  	unsigned short smallblks;
  	struct usb_device *dev;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1070
  	struct us_data *ss;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1071
  	int retry, i;
f8d813e34   wdenk   * Fix SDRAM timin...
1072
1073
1074
1075
1076
1077
  	ccb *srb = &usb_ccb;
  
  	if (blkcnt == 0)
  		return 0;
  
  	device &= 0xff;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1078
  	/* Setup  device */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1079
1080
1081
  	debug("
  usb_read: dev %d 
  ", device);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1082
1083
1084
1085
  	dev = NULL;
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
  		dev = usb_get_dev_index(i);
  		if (dev == NULL)
affae2bff   wdenk   Initial revision
1086
  			return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1087
  		if (dev->devnum == usb_dev_desc[device].target)
affae2bff   wdenk   Initial revision
1088
1089
  			break;
  	}
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1090
  	ss = (struct us_data *)dev->privptr;
affae2bff   wdenk   Initial revision
1091
1092
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
a0cb3fc31   Michael Trimarchi   USB storage clean...
1093
1094
1095
1096
  	srb->lun = usb_dev_desc[device].lun;
  	buf_addr = (unsigned long)buffer;
  	start = blknr;
  	blks = blkcnt;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1097

ceb4972a8   Vivek Gautam   usb: common: Weed...
1098
1099
1100
1101
  	debug("
  usb_read: dev %d startblk " LBAF ", blccnt " LBAF
  	      " buffer %lx
  ", device, start, blks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1102

affae2bff   wdenk   Initial revision
1103
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1104
1105
1106
  		/* XXX need some comment here */
  		retry = 2;
  		srb->pdata = (unsigned char *)buf_addr;
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1107
1108
  		if (blks > USB_MAX_XFER_BLK)
  			smallblks = USB_MAX_XFER_BLK;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1109
1110
  		else
  			smallblks = (unsigned short) blks;
affae2bff   wdenk   Initial revision
1111
  retry_it:
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1112
  		if (smallblks == USB_MAX_XFER_BLK)
affae2bff   wdenk   Initial revision
1113
  			usb_show_progress();
a0cb3fc31   Michael Trimarchi   USB storage clean...
1114
1115
  		srb->datalen = usb_dev_desc[device].blksz * smallblks;
  		srb->pdata = (unsigned char *)buf_addr;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1116
  		if (usb_read_10(srb, ss, start, smallblks)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1117
1118
  			debug("Read ERROR
  ");
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1119
  			usb_request_sense(srb, ss);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1120
  			if (retry--)
affae2bff   wdenk   Initial revision
1121
  				goto retry_it;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1122
  			blkcnt -= blks;
affae2bff   wdenk   Initial revision
1123
1124
  			break;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1125
1126
1127
1128
  		start += smallblks;
  		blks -= smallblks;
  		buf_addr += srb->datalen;
  	} while (blks != 0);
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1129
  	ss->flags &= ~USB_READY;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1130

ceb4972a8   Vivek Gautam   usb: common: Weed...
1131
1132
1133
1134
  	debug("usb_read: end startblk " LBAF
  	      ", blccnt %x buffer %lx
  ",
  	      start, smallblks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1135

affae2bff   wdenk   Initial revision
1136
  	usb_disable_asynch(0); /* asynch transfer allowed */
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1137
  	if (blkcnt >= USB_MAX_XFER_BLK)
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
1138
1139
  		debug("
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
1140
  	return blkcnt;
affae2bff   wdenk   Initial revision
1141
  }
ff8fef566   Sascha Silbe   Fix block device ...
1142
  unsigned long usb_stor_write(int device, lbaint_t blknr,
e81e79ede   Gabe Black   usb: Support the ...
1143
  				lbaint_t blkcnt, const void *buffer)
127e10842   Mahavir Jain   usb: write comman...
1144
  {
e81e79ede   Gabe Black   usb: Support the ...
1145
1146
  	lbaint_t start, blks;
  	uintptr_t buf_addr;
127e10842   Mahavir Jain   usb: write comman...
1147
1148
  	unsigned short smallblks;
  	struct usb_device *dev;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1149
  	struct us_data *ss;
127e10842   Mahavir Jain   usb: write comman...
1150
1151
1152
1153
1154
1155
1156
1157
  	int retry, i;
  	ccb *srb = &usb_ccb;
  
  	if (blkcnt == 0)
  		return 0;
  
  	device &= 0xff;
  	/* Setup  device */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1158
1159
1160
  	debug("
  usb_write: dev %d 
  ", device);
127e10842   Mahavir Jain   usb: write comman...
1161
1162
1163
1164
1165
1166
1167
1168
  	dev = NULL;
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
  		dev = usb_get_dev_index(i);
  		if (dev == NULL)
  			return 0;
  		if (dev->devnum == usb_dev_desc[device].target)
  			break;
  	}
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1169
  	ss = (struct us_data *)dev->privptr;
127e10842   Mahavir Jain   usb: write comman...
1170
1171
1172
1173
1174
1175
1176
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
  
  	srb->lun = usb_dev_desc[device].lun;
  	buf_addr = (unsigned long)buffer;
  	start = blknr;
  	blks = blkcnt;
127e10842   Mahavir Jain   usb: write comman...
1177

ceb4972a8   Vivek Gautam   usb: common: Weed...
1178
1179
1180
1181
  	debug("
  usb_write: dev %d startblk " LBAF ", blccnt " LBAF
  	      " buffer %lx
  ", device, start, blks, buf_addr);
127e10842   Mahavir Jain   usb: write comman...
1182
1183
1184
1185
1186
1187
1188
  
  	do {
  		/* If write fails retry for max retry count else
  		 * return with number of blocks written successfully.
  		 */
  		retry = 2;
  		srb->pdata = (unsigned char *)buf_addr;
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1189
1190
  		if (blks > USB_MAX_XFER_BLK)
  			smallblks = USB_MAX_XFER_BLK;
127e10842   Mahavir Jain   usb: write comman...
1191
1192
1193
  		else
  			smallblks = (unsigned short) blks;
  retry_it:
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1194
  		if (smallblks == USB_MAX_XFER_BLK)
127e10842   Mahavir Jain   usb: write comman...
1195
1196
1197
  			usb_show_progress();
  		srb->datalen = usb_dev_desc[device].blksz * smallblks;
  		srb->pdata = (unsigned char *)buf_addr;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1198
  		if (usb_write_10(srb, ss, start, smallblks)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1199
1200
  			debug("Write ERROR
  ");
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1201
  			usb_request_sense(srb, ss);
127e10842   Mahavir Jain   usb: write comman...
1202
1203
1204
1205
1206
1207
1208
1209
1210
  			if (retry--)
  				goto retry_it;
  			blkcnt -= blks;
  			break;
  		}
  		start += smallblks;
  		blks -= smallblks;
  		buf_addr += srb->datalen;
  	} while (blks != 0);
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1211
  	ss->flags &= ~USB_READY;
127e10842   Mahavir Jain   usb: write comman...
1212

ceb4972a8   Vivek Gautam   usb: common: Weed...
1213
1214
1215
  	debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx
  ",
  	      start, smallblks, buf_addr);
127e10842   Mahavir Jain   usb: write comman...
1216
1217
  
  	usb_disable_asynch(0); /* asynch transfer allowed */
4bee5c83e   Benoît Thébaudeau   usb_storage: Remo...
1218
  	if (blkcnt >= USB_MAX_XFER_BLK)
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
1219
1220
  		debug("
  ");
127e10842   Mahavir Jain   usb: write comman...
1221
1222
1223
  	return blkcnt;
  
  }
affae2bff   wdenk   Initial revision
1224
1225
  
  /* Probe to see if a new device is actually a Storage device */
a0cb3fc31   Michael Trimarchi   USB storage clean...
1226
1227
  int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
  		      struct us_data *ss)
affae2bff   wdenk   Initial revision
1228
  {
8f8bd565f   Tom Rix   USB Consolidate d...
1229
  	struct usb_interface *iface;
affae2bff   wdenk   Initial revision
1230
  	int i;
605bd75af   Vivek Gautam   USB: Some cleanup...
1231
  	struct usb_endpoint_descriptor *ep_desc;
affae2bff   wdenk   Initial revision
1232
1233
1234
1235
  	unsigned int flags = 0;
  
  	int protocol = 0;
  	int subclass = 0;
affae2bff   wdenk   Initial revision
1236
1237
1238
1239
1240
  	/* let's examine the device now */
  	iface = &dev->config.if_desc[ifnum];
  
  #if 0
  	/* this is the place to patch some storage devices */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1241
1242
  	debug("iVendor %X iProduct %X
  ", dev->descriptor.idVendor,
a0cb3fc31   Michael Trimarchi   USB storage clean...
1243
1244
1245
1246
  			dev->descriptor.idProduct);
  
  	if ((dev->descriptor.idVendor) == 0x066b &&
  	    (dev->descriptor.idProduct) == 0x0103) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1247
1248
  		debug("patched for E-USB
  ");
affae2bff   wdenk   Initial revision
1249
1250
1251
1252
1253
1254
  		protocol = US_PR_CB;
  		subclass = US_SC_UFI;	    /* an assumption */
  	}
  #endif
  
  	if (dev->descriptor.bDeviceClass != 0 ||
8f8bd565f   Tom Rix   USB Consolidate d...
1255
1256
1257
  			iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
  			iface->desc.bInterfaceSubClass < US_SC_MIN ||
  			iface->desc.bInterfaceSubClass > US_SC_MAX) {
affae2bff   wdenk   Initial revision
1258
1259
1260
  		/* if it's not a mass storage, we go no further */
  		return 0;
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1261
  	memset(ss, 0, sizeof(struct us_data));
affae2bff   wdenk   Initial revision
1262
  	/* At this point, we know we've got a live one */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1263
1264
1265
1266
  	debug("
  
  USB Mass Storage device detected
  ");
affae2bff   wdenk   Initial revision
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
  
  	/* Initialize the us_data structure with some useful info */
  	ss->flags = flags;
  	ss->ifnum = ifnum;
  	ss->pusb_dev = dev;
  	ss->attention_done = 0;
  
  	/* If the device has subclass and protocol, then use that.  Otherwise,
  	 * take data from the specific interface.
  	 */
  	if (subclass) {
  		ss->subclass = subclass;
  		ss->protocol = protocol;
  	} else {
8f8bd565f   Tom Rix   USB Consolidate d...
1281
1282
  		ss->subclass = iface->desc.bInterfaceSubClass;
  		ss->protocol = iface->desc.bInterfaceProtocol;
affae2bff   wdenk   Initial revision
1283
1284
1285
  	}
  
  	/* set the handler pointers based on the protocol */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1286
  	debug("Transport: ");
affae2bff   wdenk   Initial revision
1287
1288
  	switch (ss->protocol) {
  	case US_PR_CB:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1289
1290
  		debug("Control/Bulk
  ");
affae2bff   wdenk   Initial revision
1291
1292
1293
1294
1295
  		ss->transport = usb_stor_CB_transport;
  		ss->transport_reset = usb_stor_CB_reset;
  		break;
  
  	case US_PR_CBI:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1296
1297
  		debug("Control/Bulk/Interrupt
  ");
affae2bff   wdenk   Initial revision
1298
1299
1300
  		ss->transport = usb_stor_CB_transport;
  		ss->transport_reset = usb_stor_CB_reset;
  		break;
149dded2b   wdenk   * Add support for...
1301
  	case US_PR_BULK:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1302
1303
  		debug("Bulk/Bulk/Bulk
  ");
149dded2b   wdenk   * Add support for...
1304
1305
1306
  		ss->transport = usb_stor_BBB_transport;
  		ss->transport_reset = usb_stor_BBB_reset;
  		break;
affae2bff   wdenk   Initial revision
1307
  	default:
80885a9d5   wdenk   * Patch by Markus...
1308
1309
  		printf("USB Storage Transport unknown / not yet implemented
  ");
affae2bff   wdenk   Initial revision
1310
1311
1312
1313
1314
1315
1316
1317
1318
  		return 0;
  		break;
  	}
  
  	/*
  	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
  	 * An optional interrupt is OK (necessary for CBI protocol).
  	 * We will ignore any others.
  	 */
8f8bd565f   Tom Rix   USB Consolidate d...
1319
  	for (i = 0; i < iface->desc.bNumEndpoints; i++) {
605bd75af   Vivek Gautam   USB: Some cleanup...
1320
  		ep_desc = &iface->ep_desc[i];
affae2bff   wdenk   Initial revision
1321
  		/* is it an BULK endpoint? */
605bd75af   Vivek Gautam   USB: Some cleanup...
1322
  		if ((ep_desc->bmAttributes &
a0cb3fc31   Michael Trimarchi   USB storage clean...
1323
  		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
605bd75af   Vivek Gautam   USB: Some cleanup...
1324
1325
1326
  			if (ep_desc->bEndpointAddress & USB_DIR_IN)
  				ss->ep_in = ep_desc->bEndpointAddress &
  						USB_ENDPOINT_NUMBER_MASK;
affae2bff   wdenk   Initial revision
1327
  			else
a0cb3fc31   Michael Trimarchi   USB storage clean...
1328
  				ss->ep_out =
605bd75af   Vivek Gautam   USB: Some cleanup...
1329
  					ep_desc->bEndpointAddress &
affae2bff   wdenk   Initial revision
1330
1331
1332
1333
  					USB_ENDPOINT_NUMBER_MASK;
  		}
  
  		/* is it an interrupt endpoint? */
605bd75af   Vivek Gautam   USB: Some cleanup...
1334
1335
1336
1337
1338
  		if ((ep_desc->bmAttributes &
  		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
  			ss->ep_int = ep_desc->bEndpointAddress &
  						USB_ENDPOINT_NUMBER_MASK;
  			ss->irqinterval = ep_desc->bInterval;
affae2bff   wdenk   Initial revision
1339
1340
  		}
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
1341
1342
1343
  	debug("Endpoints In %d Out %d Int %d
  ",
  	      ss->ep_in, ss->ep_out, ss->ep_int);
affae2bff   wdenk   Initial revision
1344
1345
  
  	/* Do some basic sanity checks, and bail if we find a problem */
8f8bd565f   Tom Rix   USB Consolidate d...
1346
  	if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
affae2bff   wdenk   Initial revision
1347
1348
  	    !ss->ep_in || !ss->ep_out ||
  	    (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1349
1350
  		debug("Problems with device
  ");
affae2bff   wdenk   Initial revision
1351
1352
1353
  		return 0;
  	}
  	/* set class specific stuff */
149dded2b   wdenk   * Add support for...
1354
1355
  	/* We only handle certain protocols.  Currently, these are
  	 * the only ones.
80885a9d5   wdenk   * Patch by Markus...
1356
  	 * The SFF8070 accepts the requests used in u-boot
affae2bff   wdenk   Initial revision
1357
  	 */
80885a9d5   wdenk   * Patch by Markus...
1358
1359
  	if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
  	    ss->subclass != US_SC_8070) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1360
1361
  		printf("Sorry, protocol %d not yet supported.
  ", ss->subclass);
affae2bff   wdenk   Initial revision
1362
1363
  		return 0;
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1364
1365
1366
1367
  	if (ss->ep_int) {
  		/* we had found an interrupt endpoint, prepare irq pipe
  		 * set up the IRQ pipe and handler
  		 */
affae2bff   wdenk   Initial revision
1368
1369
1370
  		ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
  		ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
  		ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1371
  		dev->irq_handle = usb_stor_irq;
affae2bff   wdenk   Initial revision
1372
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1373
  	dev->privptr = (void *)ss;
affae2bff   wdenk   Initial revision
1374
1375
  	return 1;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
1376
1377
  int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
  		      block_dev_desc_t *dev_desc)
affae2bff   wdenk   Initial revision
1378
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1379
  	unsigned char perq, modi;
f57661394   Puneet Saxena   USB: Align buffer...
1380
1381
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1382
  	unsigned long *capacity, *blksz;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1383
  	ccb *pccb = &usb_ccb;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1384
1385
1386
1387
  	pccb->pdata = usb_stor_buf;
  
  	dev_desc->target = dev->devnum;
  	pccb->lun = dev_desc->lun;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1388
1389
  	debug(" address %d
  ", dev_desc->target);
affae2bff   wdenk   Initial revision
1390

a0cb3fc31   Michael Trimarchi   USB storage clean...
1391
  	if (usb_inquiry(pccb, ss))
affae2bff   wdenk   Initial revision
1392
  		return -1;
095b8a379   Wolfgang Denk   Coding style cleanup
1393

9c998aa83   Wolfgang Denk   Fix low-level OHC...
1394
1395
  	perq = usb_stor_buf[0];
  	modi = usb_stor_buf[1];
a0cb3fc31   Michael Trimarchi   USB storage clean...
1396
1397
1398
1399
  
  	if ((perq & 0x1f) == 0x1f) {
  		/* skip unknown devices */
  		return 0;
affae2bff   wdenk   Initial revision
1400
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1401
1402
  	if ((modi&0x80) == 0x80) {
  		/* drive is removable */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1403
  		dev_desc->removable = 1;
affae2bff   wdenk   Initial revision
1404
  	}
f57661394   Puneet Saxena   USB: Align buffer...
1405
1406
1407
  	memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
  	memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
  	memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1408
1409
1410
  	dev_desc->vendor[8] = 0;
  	dev_desc->product[16] = 0;
  	dev_desc->revision[4] = 0;
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1411
  #ifdef CONFIG_USB_BIN_FIXUP
a0cb3fc31   Michael Trimarchi   USB storage clean...
1412
1413
  	usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
  		      (uchar *)dev_desc->product);
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1414
  #endif /* CONFIG_USB_BIN_FIXUP */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1415
1416
1417
  	debug("ISO Vers %X, Response Data %X
  ", usb_stor_buf[2],
  	      usb_stor_buf[3]);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1418
1419
1420
1421
1422
1423
1424
1425
  	if (usb_test_unit_ready(pccb, ss)) {
  		printf("Device NOT ready
  "
  		       "   Request Sense returned %02X %02X %02X
  ",
  		       pccb->sense_buf[2], pccb->sense_buf[12],
  		       pccb->sense_buf[13]);
  		if (dev_desc->removable == 1) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1426
  			dev_desc->type = perq;
affae2bff   wdenk   Initial revision
1427
1428
  			return 1;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1429
  		return 0;
affae2bff   wdenk   Initial revision
1430
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1431
  	pccb->pdata = (unsigned char *)&cap[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
1432
1433
  	memset(pccb->pdata, 0, 8);
  	if (usb_read_capacity(pccb, ss) != 0) {
affae2bff   wdenk   Initial revision
1434
1435
  		printf("READ_CAP ERROR
  ");
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1436
1437
  		cap[0] = 2880;
  		cap[1] = 0x200;
affae2bff   wdenk   Initial revision
1438
  	}
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1439
  	ss->flags &= ~USB_READY;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1440
1441
  	debug("Read Capacity returns: 0x%lx, 0x%lx
  ", cap[0], cap[1]);
affae2bff   wdenk   Initial revision
1442
  #if 0
a0cb3fc31   Michael Trimarchi   USB storage clean...
1443
1444
  	if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
  		cap[0] >>= 16;
affae2bff   wdenk   Initial revision
1445
  #endif
c918261c6   Christian Eggers   USB: replace old ...
1446
1447
  	cap[0] = cpu_to_be32(cap[0]);
  	cap[1] = cpu_to_be32(cap[1]);
149dded2b   wdenk   * Add support for...
1448
  	/* this assumes bigendian! */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1449
1450
1451
  	cap[0] += 1;
  	capacity = &cap[0];
  	blksz = &cap[1];
ceb4972a8   Vivek Gautam   usb: common: Weed...
1452
1453
  	debug("Capacity = 0x%lx, blocksz = 0x%lx
  ", *capacity, *blksz);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1454
1455
  	dev_desc->lba = *capacity;
  	dev_desc->blksz = *blksz;
0472fbfd3   Egbert Eich   part/dev_desc: Ad...
1456
  	dev_desc->log2blksz = LOG2(dev_desc->blksz);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1457
  	dev_desc->type = perq;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1458
1459
1460
1461
  	debug(" address %d
  ", dev_desc->target);
  	debug("partype: %d
  ", dev_desc->part_type);
affae2bff   wdenk   Initial revision
1462
1463
  
  	init_part(dev_desc);
ceb4972a8   Vivek Gautam   usb: common: Weed...
1464
1465
  	debug("partype: %d
  ", dev_desc->part_type);
affae2bff   wdenk   Initial revision
1466
1467
  	return 1;
  }