Blame view

common/usb_storage.c 42.1 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
acf277af6   Simon Glass   dm: usb: Convert ...
12
13
   * Driver model conversion:
   *   (C) Copyright 2015 Google, Inc
affae2bff   wdenk   Initial revision
14
   *
149dded2b   wdenk   * Add support for...
15
   * For BBB support (C) Copyright 2003
792a09eb9   Detlev Zundel   Fix e-mail addres...
16
   * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
149dded2b   wdenk   * Add support for...
17
   *
460c322f1   Wolfgang Denk   (re)enabled scsi ...
18
   * BBB support based on /sys/dev/usb/umass.c from
149dded2b   wdenk   * Add support for...
19
   * FreeBSD.
affae2bff   wdenk   Initial revision
20
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
21
   * SPDX-License-Identifier:	GPL-2.0+
affae2bff   wdenk   Initial revision
22
23
24
25
26
27
28
   */
  
  /* 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...
29
30
31
32
  /*
   * 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...
33
   */
affae2bff   wdenk   Initial revision
34

affae2bff   wdenk   Initial revision
35
36
  #include <common.h>
  #include <command.h>
acf277af6   Simon Glass   dm: usb: Convert ...
37
  #include <dm.h>
91557579a   Simon Glass   dm: usb: Move sto...
38
  #include <errno.h>
4fd074de0   Simon Glass   usb: Use correct ...
39
  #include <inttypes.h>
051081323   Simon Glass   dm: usb: Adjust u...
40
  #include <mapmem.h>
cf92e05c0   Simon Glass   Move ALLOC_CACHE_...
41
  #include <memalign.h>
c918261c6   Christian Eggers   USB: replace old ...
42
  #include <asm/byteorder.h>
affae2bff   wdenk   Initial revision
43
  #include <asm/processor.h>
acf277af6   Simon Glass   dm: usb: Convert ...
44
  #include <dm/device-internal.h>
07b2b78ce   Simon Glass   dm: usb: Convert ...
45
  #include <dm/lists.h>
affae2bff   wdenk   Initial revision
46

735dd97b1   Grant Likely   [PATCH 1_4] Merge...
47
  #include <part.h>
affae2bff   wdenk   Initial revision
48
  #include <usb.h>
80885a9d5   wdenk   * Patch by Markus...
49
50
  #undef BBB_COMDAT_TRACE
  #undef BBB_XPORT_TRACE
affae2bff   wdenk   Initial revision
51

affae2bff   wdenk   Initial revision
52
53
54
55
  #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...
56
  static const unsigned char us_direction[256/8] = {
affae2bff   wdenk   Initial revision
57
58
59
60
61
62
  	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)
b9560ad64   Simon Glass   dm: scsi: Drop th...
63
  static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
a0cb3fc31   Michael Trimarchi   USB storage clean...
64
  static __u32 CBWTag;
149dded2b   wdenk   * Add support for...
65

a0cb3fc31   Michael Trimarchi   USB storage clean...
66
  static int usb_max_devs; /* number of highest available usb device */
affae2bff   wdenk   Initial revision
67

07b2b78ce   Simon Glass   dm: usb: Convert ...
68
  #ifndef CONFIG_BLK
4101f6879   Simon Glass   dm: Drop the bloc...
69
  static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
07b2b78ce   Simon Glass   dm: usb: Convert ...
70
  #endif
affae2bff   wdenk   Initial revision
71
72
  
  struct us_data;
b9560ad64   Simon Glass   dm: scsi: Drop th...
73
  typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
a0cb3fc31   Michael Trimarchi   USB storage clean...
74
  typedef int (*trans_reset)(struct us_data *data);
affae2bff   wdenk   Initial revision
75
76
  
  struct us_data {
a0cb3fc31   Michael Trimarchi   USB storage clean...
77
78
79
  	struct usb_device *pusb_dev;	 /* this usb_device */
  
  	unsigned int	flags;			/* from filter initially */
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
80
  #	define USB_READY	(1 << 0)
a0cb3fc31   Michael Trimarchi   USB storage clean...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  	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 */
b9560ad64   Simon Glass   dm: scsi: Drop th...
95
  	struct scsi_cmd	*srb;			/* current srb */
a0cb3fc31   Michael Trimarchi   USB storage clean...
96
97
  	trans_reset	transport_reset;	/* reset routine */
  	trans_cmnd	transport;		/* transport routine */
6158d0b42   Bin Meng   usb: storage: Ref...
98
  	unsigned short	max_xfer_blk;		/* maximum transfer blocks */
affae2bff   wdenk   Initial revision
99
  };
07b2b78ce   Simon Glass   dm: usb: Convert ...
100
  #ifndef CONFIG_BLK
affae2bff   wdenk   Initial revision
101
  static struct us_data usb_stor[USB_MAX_STOR_DEV];
07b2b78ce   Simon Glass   dm: usb: Convert ...
102
  #endif
affae2bff   wdenk   Initial revision
103

80885a9d5   wdenk   * Patch by Markus...
104
  #define USB_STOR_TRANSPORT_GOOD	   0
affae2bff   wdenk   Initial revision
105
106
  #define USB_STOR_TRANSPORT_FAILED -1
  #define USB_STOR_TRANSPORT_ERROR  -2
a0cb3fc31   Michael Trimarchi   USB storage clean...
107
  int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
4101f6879   Simon Glass   dm: Drop the bloc...
108
  		      struct blk_desc *dev_desc);
a0cb3fc31   Michael Trimarchi   USB storage clean...
109
110
  int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
  		      struct us_data *ss);
07b2b78ce   Simon Glass   dm: usb: Convert ...
111
112
113
114
115
116
  #ifdef CONFIG_BLK
  static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
  				   lbaint_t blkcnt, void *buffer);
  static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
  				    lbaint_t blkcnt, const void *buffer);
  #else
4101f6879   Simon Glass   dm: Drop the bloc...
117
  static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
118
  				   lbaint_t blkcnt, void *buffer);
4101f6879   Simon Glass   dm: Drop the bloc...
119
  static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
120
  				    lbaint_t blkcnt, const void *buffer);
07b2b78ce   Simon Glass   dm: usb: Convert ...
121
  #endif
affae2bff   wdenk   Initial revision
122
  void uhci_show_temp_int_td(void);
199adb601   Kim Phillips   common/misc: spar...
123
  static void usb_show_progress(void)
affae2bff   wdenk   Initial revision
124
  {
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
125
  	debug(".");
affae2bff   wdenk   Initial revision
126
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
127
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
128
129
130
   * 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 ...
131
  int usb_stor_info(void)
9c998aa83   Wolfgang Denk   Fix low-level OHC...
132
  {
9807c3b78   Simon Glass   dm: usb: Tidy up ...
133
  	int count = 0;
07b2b78ce   Simon Glass   dm: usb: Convert ...
134
135
136
137
138
139
140
141
142
143
144
145
146
  #ifdef CONFIG_BLK
  	struct udevice *dev;
  
  	for (blk_first_device(IF_TYPE_USB, &dev);
  	     dev;
  	     blk_next_device(&dev)) {
  		struct blk_desc *desc = dev_get_uclass_platdata(dev);
  
  		printf("  Device %d: ", desc->devnum);
  		dev_print(desc);
  		count++;
  	}
  #else
9c998aa83   Wolfgang Denk   Fix low-level OHC...
147
  	int i;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
148
  	if (usb_max_devs > 0) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
149
  		for (i = 0; i < usb_max_devs; i++) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
150
  			printf("  Device %d: ", i);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
151
152
  			dev_print(&usb_dev_desc[i]);
  		}
b9e749e95   Markus Klotzbuecher   USB, Storage: fix...
153
  		return 0;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
154
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
155
  #endif
9807c3b78   Simon Glass   dm: usb: Tidy up ...
156
157
158
159
160
  	if (!count) {
  		printf("No storage devices, perhaps not 'usb start'ed..?
  ");
  		return 1;
  	}
b94fc8518   Simon Glass   usb: Correct retu...
161
  	return 0;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
162
  }
99e9ed1f4   Ludovic Courtès   usb: Add support ...
163
164
165
  static unsigned int usb_get_max_lun(struct us_data *us)
  {
  	int len;
f57661394   Puneet Saxena   USB: Align buffer...
166
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
99e9ed1f4   Ludovic Courtès   usb: Add support ...
167
168
169
170
171
  	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...
172
  			      result, sizeof(char),
99e9ed1f4   Ludovic Courtès   usb: Add support ...
173
  			      USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
174
175
  	debug("Get Max LUN -> len = %i, result = %i
  ", len, (int) *result);
f57661394   Puneet Saxena   USB: Align buffer...
176
  	return (len > 0) ? *result : 0;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
177
  }
9807c3b78   Simon Glass   dm: usb: Tidy up ...
178
  static int usb_stor_probe_device(struct usb_device *udev)
91557579a   Simon Glass   dm: usb: Move sto...
179
  {
9807c3b78   Simon Glass   dm: usb: Tidy up ...
180
  	int lun, max_lun;
07b2b78ce   Simon Glass   dm: usb: Convert ...
181
182
183
  
  #ifdef CONFIG_BLK
  	struct us_data *data;
07b2b78ce   Simon Glass   dm: usb: Convert ...
184
185
  	int ret;
  #else
9807c3b78   Simon Glass   dm: usb: Tidy up ...
186
187
188
  	int start;
  
  	if (udev == NULL)
91557579a   Simon Glass   dm: usb: Move sto...
189
  		return -ENOENT; /* no more devices available */
07b2b78ce   Simon Glass   dm: usb: Convert ...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  #endif
  
  	debug("
  
  Probing for storage
  ");
  #ifdef CONFIG_BLK
  	/*
  	 * We store the us_data in the mass storage device's platdata. It
  	 * is shared by all LUNs (block devices) attached to this mass storage
  	 * device.
  	 */
  	data = dev_get_platdata(udev->dev);
  	if (!usb_storage_probe(udev, 0, data))
  		return 0;
  	max_lun = usb_get_max_lun(data);
  	for (lun = 0; lun <= max_lun; lun++) {
  		struct blk_desc *blkdev;
  		struct udevice *dev;
9107c973d   Simon Glass   dm: blk: Add a ea...
209
  		char str[10];
07b2b78ce   Simon Glass   dm: usb: Convert ...
210

9107c973d   Simon Glass   dm: blk: Add a ea...
211
212
213
214
  		snprintf(str, sizeof(str), "lun%d", lun);
  		ret = blk_create_devicef(udev->dev, "usb_storage_blk", str,
  					 IF_TYPE_USB, usb_max_devs, 512, 0,
  					 &dev);
07b2b78ce   Simon Glass   dm: usb: Convert ...
215
216
217
218
219
220
221
222
223
  		if (ret) {
  			debug("Cannot bind driver
  ");
  			return ret;
  		}
  
  		blkdev = dev_get_uclass_platdata(dev);
  		blkdev->target = 0xff;
  		blkdev->lun = lun;
91557579a   Simon Glass   dm: usb: Move sto...
224

07b2b78ce   Simon Glass   dm: usb: Convert ...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  		ret = usb_stor_get_info(udev, data, blkdev);
  		if (ret == 1)
  			ret = blk_prepare_device(dev);
  		if (!ret) {
  			usb_max_devs++;
  			debug("%s: Found device %p
  ", __func__, udev);
  		} else {
  			debug("usb_stor_get_info: Invalid device
  ");
  			ret = device_unbind(dev);
  			if (ret)
  				return ret;
  		}
  	}
  #else
c89e79d41   Simon Glass   dm: usb: Avoid ex...
241
242
243
244
245
246
247
  	/* We don't have space to even probe if we hit the maximum */
  	if (usb_max_devs == USB_MAX_STOR_DEV) {
  		printf("max USB Storage Device reached: %d stopping
  ",
  		       usb_max_devs);
  		return -ENOSPC;
  	}
9807c3b78   Simon Glass   dm: usb: Tidy up ...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  	if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs]))
  		return 0;
  
  	/*
  	 * OK, it's a storage device.  Iterate over its LUNs and populate
  	 * usb_dev_desc'
  	 */
  	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++) {
  		struct blk_desc *blkdev;
  
  		blkdev = &usb_dev_desc[usb_max_devs];
  		memset(blkdev, '\0', sizeof(struct blk_desc));
  		blkdev->if_type = IF_TYPE_USB;
  		blkdev->devnum = usb_max_devs;
  		blkdev->part_type = PART_TYPE_UNKNOWN;
  		blkdev->target = 0xff;
  		blkdev->type = DEV_TYPE_UNKNOWN;
  		blkdev->block_read = usb_stor_read;
  		blkdev->block_write = usb_stor_write;
  		blkdev->lun = lun;
  		blkdev->priv = udev;
  
  		if (usb_stor_get_info(udev, &usb_stor[start],
  				      &usb_dev_desc[usb_max_devs]) == 1) {
07b2b78ce   Simon Glass   dm: usb: Convert ...
276
277
278
279
280
  			debug("partype: %d
  ", blkdev->part_type);
  			part_init(blkdev);
  			debug("partype: %d
  ", blkdev->part_type);
9807c3b78   Simon Glass   dm: usb: Tidy up ...
281
282
283
  			usb_max_devs++;
  			debug("%s: Found device %p
  ", __func__, udev);
91557579a   Simon Glass   dm: usb: Move sto...
284
285
  		}
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
286
  #endif
91557579a   Simon Glass   dm: usb: Move sto...
287

91557579a   Simon Glass   dm: usb: Move sto...
288
289
290
291
292
293
294
  	return 0;
  }
  
  void usb_stor_reset(void)
  {
  	usb_max_devs = 0;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
295
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
296
   * scan the usb and reports device info
affae2bff   wdenk   Initial revision
297
298
299
300
301
   * to the user if mode = 1
   * returns current device or -1 if no
   */
  int usb_stor_scan(int mode)
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
302
  	if (mode == 1)
93c2582fe   Lucas Stach   usb: add support ...
303
  		printf("       scanning usb for storage devices... ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
304

b984700ca   Michal Simek   usb: storage: Sho...
305
306
  #ifndef CONFIG_DM_USB
  	unsigned char i;
affae2bff   wdenk   Initial revision
307
  	usb_disable_asynch(1); /* asynch transfer not allowed */
91557579a   Simon Glass   dm: usb: Move sto...
308
  	usb_stor_reset();
a0cb3fc31   Michael Trimarchi   USB storage clean...
309
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
91557579a   Simon Glass   dm: usb: Move sto...
310
  		struct usb_device *dev;
a0cb3fc31   Michael Trimarchi   USB storage clean...
311
  		dev = usb_get_dev_index(i); /* get device */
ceb4972a8   Vivek Gautam   usb: common: Weed...
312
313
  		debug("i=%d
  ", i);
91557579a   Simon Glass   dm: usb: Move sto...
314
  		if (usb_stor_probe_device(dev))
affae2bff   wdenk   Initial revision
315
  			break;
affae2bff   wdenk   Initial revision
316
  	} /* for */
095b8a379   Wolfgang Denk   Coding style cleanup
317

affae2bff   wdenk   Initial revision
318
  	usb_disable_asynch(0); /* asynch transfer allowed */
b984700ca   Michal Simek   usb: storage: Sho...
319
  #endif
9c998aa83   Wolfgang Denk   Fix low-level OHC...
320
321
  	printf("%d Storage Device(s) found
  ", usb_max_devs);
a0cb3fc31   Michael Trimarchi   USB storage clean...
322
  	if (usb_max_devs > 0)
affae2bff   wdenk   Initial revision
323
  		return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
324
  	return -1;
affae2bff   wdenk   Initial revision
325
326
327
328
329
  }
  
  static int usb_stor_irq(struct usb_device *dev)
  {
  	struct us_data *us;
a0cb3fc31   Michael Trimarchi   USB storage clean...
330
  	us = (struct us_data *)dev->privptr;
affae2bff   wdenk   Initial revision
331

a0cb3fc31   Michael Trimarchi   USB storage clean...
332
333
  	if (us->ip_wanted)
  		us->ip_wanted = 0;
affae2bff   wdenk   Initial revision
334
335
  	return 0;
  }
ceb4972a8   Vivek Gautam   usb: common: Weed...
336
  #ifdef	DEBUG
affae2bff   wdenk   Initial revision
337

b9560ad64   Simon Glass   dm: scsi: Drop th...
338
  static void usb_show_srb(struct scsi_cmd *pccb)
affae2bff   wdenk   Initial revision
339
340
  {
  	int i;
a0cb3fc31   Michael Trimarchi   USB storage clean...
341
342
343
344
  	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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  	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 */
051081323   Simon Glass   dm: usb: Adjust u...
391
392
393
394
  			debug("Bulk xfer 0x%lx(%d) try #%d
  ",
  			      (ulong)map_to_sysmem(buf), this_xfer,
  			      11 - maxtry);
affae2bff   wdenk   Initial revision
395
  			result = usb_bulk_msg(us->pusb_dev, pipe, buf,
a0cb3fc31   Michael Trimarchi   USB storage clean...
396
397
  					      this_xfer, &partial,
  					      USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
398
399
400
  			debug("bulk_msg returned %d xferred %d/%d
  ",
  			      result, partial, this_xfer);
a0cb3fc31   Michael Trimarchi   USB storage clean...
401
402
403
404
  			if (us->pusb_dev->status != 0) {
  				/* if we stall, we need to clear it before
  				 * we go on
  				 */
ceb4972a8   Vivek Gautam   usb: common: Weed...
405
  #ifdef DEBUG
affae2bff   wdenk   Initial revision
406
407
408
  				display_int_status(us->pusb_dev->status);
  #endif
  				if (us->pusb_dev->status & USB_ST_STALLED) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
409
410
411
  					debug("stalled ->clearing endpoint" \
  					      "halt for pipe 0x%x
  ", pipe);
affae2bff   wdenk   Initial revision
412
413
  					stat = us->pusb_dev->status;
  					usb_clear_halt(us->pusb_dev, pipe);
a0cb3fc31   Michael Trimarchi   USB storage clean...
414
415
  					us->pusb_dev->status = stat;
  					if (this_xfer == partial) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
416
417
418
419
420
  						debug("bulk transferred" \
  						      "with error %lX," \
  						      " but data ok
  ",
  						      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
421
422
423
424
425
426
  						return 0;
  					}
  					else
  						return result;
  				}
  				if (us->pusb_dev->status & USB_ST_NAK_REC) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
427
428
  					debug("Device NAKed bulk_msg
  ");
affae2bff   wdenk   Initial revision
429
430
  					return result;
  				}
ceb4972a8   Vivek Gautam   usb: common: Weed...
431
  				debug("bulk transferred with error");
a0cb3fc31   Michael Trimarchi   USB storage clean...
432
  				if (this_xfer == partial) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
433
434
435
  					debug(" %ld, but data ok
  ",
  					      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
436
437
438
  					return 0;
  				}
  				/* if our try counter reaches 0, bail out */
ceb4972a8   Vivek Gautam   usb: common: Weed...
439
440
441
  					debug(" %ld, data %d
  ",
  					      us->pusb_dev->status, partial);
affae2bff   wdenk   Initial revision
442
443
444
445
446
447
448
  				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...
449
  		} while (this_xfer);
affae2bff   wdenk   Initial revision
450
451
452
453
454
  	}
  
  	/* if we get here, we're done and successful */
  	return 0;
  }
149dded2b   wdenk   * Add support for...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  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...
474
475
  	debug("BBB_reset
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
476
477
478
  	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...
479
  				 0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
480

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

149dded2b   wdenk   * Add support for...
487
  	/* long wait for reset */
5b84dd67c   Mike Frysinger   usb: replace wait...
488
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
489
490
491
  	debug("BBB_reset result %d: status %lX reset
  ",
  	      result, us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
492
493
494
  	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...
495
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
496
497
498
  	debug("BBB_reset result %d: status %lX clearing IN endpoint
  ",
  	      result, us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
499
500
501
  	/* 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...
502
  	mdelay(150);
ceb4972a8   Vivek Gautam   usb: common: Weed...
503
504
505
506
507
  	debug("BBB_reset result %d: status %lX clearing OUT endpoint
  ",
  	      result, us->pusb_dev->status);
  	debug("BBB_reset done
  ");
149dded2b   wdenk   * Add support for...
508
509
  	return 0;
  }
affae2bff   wdenk   Initial revision
510
511
512
513
514
515
516
517
  /* 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...
518
519
  	debug("CB_reset
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
520
  	memset(cmd, 0xff, sizeof(cmd));
affae2bff   wdenk   Initial revision
521
522
  	cmd[0] = SCSI_SEND_DIAG;
  	cmd[1] = 4;
a0cb3fc31   Michael Trimarchi   USB storage clean...
523
524
525
526
527
  	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
528
529
  
  	/* long wait for reset */
5b84dd67c   Mike Frysinger   usb: replace wait...
530
  	mdelay(1500);
ceb4972a8   Vivek Gautam   usb: common: Weed...
531
532
533
  	debug("CB_reset result %d: status %lX clearing endpoint halt
  ",
  	      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
534
535
  	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...
536
537
  	debug("CB_reset done
  ");
affae2bff   wdenk   Initial revision
538
539
  	return 0;
  }
149dded2b   wdenk   * Add support for...
540
541
542
543
  /*
   * Set up the command for a BBB device. Note that the actual SCSI
   * command is copied into cbw.CBWCDB.
   */
b9560ad64   Simon Glass   dm: scsi: Drop th...
544
  static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
149dded2b   wdenk   * Add support for...
545
546
547
548
549
  {
  	int result;
  	int actlen;
  	int dir_in;
  	unsigned int pipe;
2e17c87eb   Simon Glass   dm: usb: Move USB...
550
  	ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
149dded2b   wdenk   * Add support for...
551
552
553
554
  
  	dir_in = US_DIRECTION(srb->cmd[0]);
  
  #ifdef BBB_COMDAT_TRACE
605bd75af   Vivek Gautam   USB: Some cleanup...
555
556
  	printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p
  ",
a0cb3fc31   Michael Trimarchi   USB storage clean...
557
558
  		dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
  		srb->pdata);
149dded2b   wdenk   * Add support for...
559
  	if (srb->cmdlen) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
560
  		for (result = 0; result < srb->cmdlen; result++)
149dded2b   wdenk   * Add support for...
561
562
563
564
565
566
567
  			printf("cmd[%d] %#x ", result, srb->cmd[result]);
  		printf("
  ");
  	}
  #endif
  	/* sanity checks */
  	if (!(srb->cmdlen <= CBWCDBLENGTH)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
568
569
  		debug("usb_stor_BBB_comdat:cmdlen too large
  ");
149dded2b   wdenk   * Add support for...
570
571
572
573
574
  		return -1;
  	}
  
  	/* always OUT to the ep */
  	pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
f57661394   Puneet Saxena   USB: Align buffer...
575
576
577
578
579
580
  	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...
581
582
  	/* copy the command data into the CBW command data buffer */
  	/* DST SRC LEN!!! */
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
583

f57661394   Puneet Saxena   USB: Align buffer...
584
585
  	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...
586
  			      &actlen, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
587
  	if (result < 0)
ceb4972a8   Vivek Gautam   usb: common: Weed...
588
589
  		debug("usb_stor_BBB_comdat:usb_bulk_msg error
  ");
149dded2b   wdenk   * Add support for...
590
591
  	return result;
  }
affae2bff   wdenk   Initial revision
592
593
594
  /* FIXME: we also need a CBI_command which sets up the completion
   * interrupt, and waits for it
   */
b9560ad64   Simon Glass   dm: scsi: Drop th...
595
  static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
596
  {
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
597
  	int result = 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
598
  	int dir_in, retry;
affae2bff   wdenk   Initial revision
599
600
  	unsigned int pipe;
  	unsigned long status;
a0cb3fc31   Michael Trimarchi   USB storage clean...
601
602
  	retry = 5;
  	dir_in = US_DIRECTION(srb->cmd[0]);
affae2bff   wdenk   Initial revision
603

a0cb3fc31   Michael Trimarchi   USB storage clean...
604
605
606
607
608
609
  	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...
610
611
612
  		debug("CBI gets a command: Try %d
  ", 5 - retry);
  #ifdef DEBUG
affae2bff   wdenk   Initial revision
613
614
615
  		usb_show_srb(srb);
  #endif
  		/* let's send the command via the control pipe */
a0cb3fc31   Michael Trimarchi   USB storage clean...
616
617
618
619
  		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
620
  					 0, us->ifnum,
a0cb3fc31   Michael Trimarchi   USB storage clean...
621
622
  					 srb->cmd, srb->cmdlen,
  					 USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
623
624
625
  		debug("CB_transport: control msg returned %d, status %lX
  ",
  		      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
626
627
  		/* check the return code for the command */
  		if (result < 0) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
628
629
  			if (us->pusb_dev->status & USB_ST_STALLED) {
  				status = us->pusb_dev->status;
ceb4972a8   Vivek Gautam   usb: common: Weed...
630
631
632
  				debug(" stall during command found," \
  				      " clear pipe
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
633
634
635
  				usb_clear_halt(us->pusb_dev,
  					      usb_sndctrlpipe(us->pusb_dev, 0));
  				us->pusb_dev->status = status;
affae2bff   wdenk   Initial revision
636
  			}
ceb4972a8   Vivek Gautam   usb: common: Weed...
637
638
639
640
  			debug(" error during command %02X" \
  			      " Stat = %lX
  ", srb->cmd[0],
  			      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
641
642
643
  			return result;
  		}
  		/* transfer the data payload for this command, if one exists*/
ceb4972a8   Vivek Gautam   usb: common: Weed...
644
645
646
647
  		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
648
  		if (srb->datalen) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
649
650
  			result = us_one_transfer(us, pipe, (char *)srb->pdata,
  						 srb->datalen);
ceb4972a8   Vivek Gautam   usb: common: Weed...
651
652
653
654
655
  			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...
656
  			if (!(us->pusb_dev->status & USB_ST_NAK_REC))
affae2bff   wdenk   Initial revision
657
658
659
660
661
662
663
664
665
  				break;
  		} /* if (srb->datalen) */
  		else
  			break;
  	}
  	/* return result */
  
  	return result;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
666
  static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
667
668
  {
  	int timeout;
80885a9d5   wdenk   * Patch by Markus...
669
  	us->ip_wanted = 1;
a0cb3fc31   Michael Trimarchi   USB storage clean...
670
  	submit_int_msg(us->pusb_dev, us->irqpipe,
80885a9d5   wdenk   * Patch by Markus...
671
672
673
  			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
  	timeout = 1000;
  	while (timeout--) {
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
674
  		if (us->ip_wanted == 0)
affae2bff   wdenk   Initial revision
675
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
676
  		mdelay(10);
affae2bff   wdenk   Initial revision
677
678
  	}
  	if (us->ip_wanted) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
679
680
  		printf("	Did not get interrupt on CBI
  ");
affae2bff   wdenk   Initial revision
681
682
683
  		us->ip_wanted = 0;
  		return USB_STOR_TRANSPORT_ERROR;
  	}
a6f70a3d1   Vagrant Cascadian   Fix spelling of "...
684
685
  	debug("Got interrupt data 0x%x, transferred %d status 0x%lX
  ",
ceb4972a8   Vivek Gautam   usb: common: Weed...
686
687
  	      us->ip_data, us->pusb_dev->irq_act_len,
  	      us->pusb_dev->irq_status);
affae2bff   wdenk   Initial revision
688
689
690
691
692
  	/* 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...
693
694
  		else if (us->ip_data)
  			return USB_STOR_TRANSPORT_FAILED;
affae2bff   wdenk   Initial revision
695
  		else
80885a9d5   wdenk   * Patch by Markus...
696
  			return USB_STOR_TRANSPORT_GOOD;
affae2bff   wdenk   Initial revision
697
698
699
  	}
  	/* otherwise, we interpret the data normally */
  	switch (us->ip_data) {
80885a9d5   wdenk   * Patch by Markus...
700
701
702
703
704
705
706
  	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
707
708
709
710
711
  	return USB_STOR_TRANSPORT_ERROR;
  }
  
  #define USB_TRANSPORT_UNKNOWN_RETRY 5
  #define USB_TRANSPORT_NOT_READY_RETRY 10
149dded2b   wdenk   * Add support for...
712
  /* clear a stall on an endpoint - special for BBB devices */
199adb601   Kim Phillips   common/misc: spar...
713
  static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
149dded2b   wdenk   * Add support for...
714
  {
149dded2b   wdenk   * Add support for...
715
  	/* ENDPOINT_HALT = 0, so set value to 0 */
8319aeb1d   Masahiro Yamada   usb: squash lines...
716
717
718
  	return usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
  			       USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
  			       endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
719
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
720
  static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
149dded2b   wdenk   * Add support for...
721
722
723
724
725
  {
  	int result, retry;
  	int dir_in;
  	int actlen, data_actlen;
  	unsigned int pipe, pipein, pipeout;
2e17c87eb   Simon Glass   dm: usb: Move USB...
726
  	ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
149dded2b   wdenk   * Add support for...
727
728
729
730
731
732
733
734
  #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...
735
736
  	debug("COMMAND phase
  ");
149dded2b   wdenk   * Add support for...
737
738
  	result = usb_stor_BBB_comdat(srb, us);
  	if (result < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
739
740
741
  		debug("failed to send CBW status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
742
743
744
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	}
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
745
746
  	if (!(us->flags & USB_READY))
  		mdelay(5);
149dded2b   wdenk   * Add support for...
747
748
749
  	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...
750
751
752
753
  	data_actlen = 0;
  	/* no data, go immediately to the STATUS phase */
  	if (srb->datalen == 0)
  		goto st;
ceb4972a8   Vivek Gautam   usb: common: Weed...
754
755
  	debug("DATA phase
  ");
149dded2b   wdenk   * Add support for...
756
757
758
759
  	if (dir_in)
  		pipe = pipein;
  	else
  		pipe = pipeout;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
760

a0cb3fc31   Michael Trimarchi   USB storage clean...
761
762
  	result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
  			      &data_actlen, USB_CNTL_TIMEOUT * 5);
149dded2b   wdenk   * Add support for...
763
  	/* special handling of STALL in DATA phase */
a0cb3fc31   Michael Trimarchi   USB storage clean...
764
  	if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
765
766
  		debug("DATA:stall
  ");
149dded2b   wdenk   * Add support for...
767
  		/* clear the STALL on the endpoint */
a0cb3fc31   Michael Trimarchi   USB storage clean...
768
769
  		result = usb_stor_BBB_clear_endpt_stall(us,
  					dir_in ? us->ep_in : us->ep_out);
149dded2b   wdenk   * Add support for...
770
771
772
773
774
  		if (result >= 0)
  			/* continue on to STATUS phase */
  			goto st;
  	}
  	if (result < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
775
776
777
  		debug("usb_bulk_msg error status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
778
779
780
781
782
783
784
785
786
787
  		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...
788
  st:
149dded2b   wdenk   * Add support for...
789
  	retry = 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
790
  again:
ceb4972a8   Vivek Gautam   usb: common: Weed...
791
792
  	debug("STATUS phase
  ");
f57661394   Puneet Saxena   USB: Align buffer...
793
  	result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
9c998aa83   Wolfgang Denk   Fix low-level OHC...
794
  				&actlen, USB_CNTL_TIMEOUT*5);
149dded2b   wdenk   * Add support for...
795
  	/* special handling of STALL in STATUS phase */
a0cb3fc31   Michael Trimarchi   USB storage clean...
796
797
  	if ((result < 0) && (retry < 1) &&
  	    (us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
798
799
  		debug("STATUS:stall
  ");
149dded2b   wdenk   * Add support for...
800
801
802
803
804
805
806
  		/* 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...
807
808
809
  		debug("usb_bulk_msg error status %ld
  ",
  		      us->pusb_dev->status);
149dded2b   wdenk   * Add support for...
810
811
812
813
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	}
  #ifdef BBB_XPORT_TRACE
f57661394   Puneet Saxena   USB: Align buffer...
814
  	ptr = (unsigned char *)csw;
149dded2b   wdenk   * Add support for...
815
816
817
818
819
820
  	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...
821
  	pipe = le32_to_cpu(csw->dCSWDataResidue);
149dded2b   wdenk   * Add support for...
822
823
  	if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
  		pipe = srb->datalen - data_actlen;
f57661394   Puneet Saxena   USB: Align buffer...
824
  	if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
825
826
  		debug("!CSWSIGNATURE
  ");
149dded2b   wdenk   * Add support for...
827
828
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
829
  	} else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
830
831
  		debug("!Tag
  ");
149dded2b   wdenk   * Add support for...
832
833
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
834
  	} else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
835
836
  		debug(">PHASE
  ");
149dded2b   wdenk   * Add support for...
837
838
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
839
  	} else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
840
841
  		debug("=PHASE
  ");
149dded2b   wdenk   * Add support for...
842
843
844
  		usb_stor_BBB_reset(us);
  		return USB_STOR_TRANSPORT_FAILED;
  	} else if (data_actlen > srb->datalen) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
845
846
847
  		debug("transferred %dB instead of %ldB
  ",
  		      data_actlen, srb->datalen);
149dded2b   wdenk   * Add support for...
848
  		return USB_STOR_TRANSPORT_FAILED;
f57661394   Puneet Saxena   USB: Align buffer...
849
  	} else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
850
851
  		debug("FAILED
  ");
149dded2b   wdenk   * Add support for...
852
853
854
855
856
  		return USB_STOR_TRANSPORT_FAILED;
  	}
  
  	return result;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
857
  static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
affae2bff   wdenk   Initial revision
858
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
859
  	int result, status;
b9560ad64   Simon Glass   dm: scsi: Drop th...
860
861
  	struct scsi_cmd *psrb;
  	struct scsi_cmd reqsrb;
a0cb3fc31   Michael Trimarchi   USB storage clean...
862
  	int retry, notready;
affae2bff   wdenk   Initial revision
863

d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
864
  	psrb = &reqsrb;
a0cb3fc31   Michael Trimarchi   USB storage clean...
865
866
867
  	status = USB_STOR_TRANSPORT_GOOD;
  	retry = 0;
  	notready = 0;
affae2bff   wdenk   Initial revision
868
869
  	/* issue the command */
  do_retry:
a0cb3fc31   Michael Trimarchi   USB storage clean...
870
  	result = usb_stor_CB_comdat(srb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
871
872
873
  	debug("command / Data returned %d, status %lX
  ",
  	      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
874
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
875
876
  	if (us->protocol == US_PR_CBI) {
  		status = usb_stor_CBI_get_status(srb, us);
affae2bff   wdenk   Initial revision
877
  		/* if the status is error, report it */
a0cb3fc31   Michael Trimarchi   USB storage clean...
878
  		if (status == USB_STOR_TRANSPORT_ERROR) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
879
880
  			debug(" USB CBI Command Error
  ");
affae2bff   wdenk   Initial revision
881
882
  			return status;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
883
884
885
886
887
  		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...
888
889
  				debug(" USB CBI Command Good
  ");
affae2bff   wdenk   Initial revision
890
891
892
893
894
895
  				return status;
  			}
  		}
  	}
  	/* do we have to issue an auto request? */
  	/* HERE we have to check the result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
896
  	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
897
898
  		debug("ERROR %lX
  ", us->pusb_dev->status);
affae2bff   wdenk   Initial revision
899
900
901
  		us->transport_reset(us);
  		return USB_STOR_TRANSPORT_ERROR;
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
902
903
904
905
  	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...
906
907
  		debug("No auto request and good
  ");
affae2bff   wdenk   Initial revision
908
909
910
  		return USB_STOR_TRANSPORT_GOOD;
  	}
  	/* issue an request_sense */
a0cb3fc31   Michael Trimarchi   USB storage clean...
911
912
913
914
915
  	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...
916
  	psrb->pdata = &srb->sense_buf[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
917
  	psrb->cmdlen = 12;
affae2bff   wdenk   Initial revision
918
  	/* issue the command */
a0cb3fc31   Michael Trimarchi   USB storage clean...
919
  	result = usb_stor_CB_comdat(psrb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
920
921
  	debug("auto request returned %d
  ", result);
affae2bff   wdenk   Initial revision
922
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
923
924
925
926
  	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...
927
928
929
  		debug(" AUTO REQUEST ERROR %ld
  ",
  		      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
930
931
  		return USB_STOR_TRANSPORT_ERROR;
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
932
933
934
935
  	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
936
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
937
938
939
940
  	if ((srb->sense_buf[2] == 0) &&
  	    (srb->sense_buf[12] == 0) &&
  	    (srb->sense_buf[13] == 0)) {
  		/* ok, no sense */
affae2bff   wdenk   Initial revision
941
  		return USB_STOR_TRANSPORT_GOOD;
a0cb3fc31   Michael Trimarchi   USB storage clean...
942
  	}
affae2bff   wdenk   Initial revision
943
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
944
945
946
  	switch (srb->sense_buf[2]) {
  	case 0x01:
  		/* Recovered Error */
149dded2b   wdenk   * Add support for...
947
  		return USB_STOR_TRANSPORT_GOOD;
80885a9d5   wdenk   * Patch by Markus...
948
  		break;
a0cb3fc31   Michael Trimarchi   USB storage clean...
949
950
951
952
953
954
955
956
  	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...
957
958
  			return USB_STOR_TRANSPORT_FAILED;
  		} else {
5b84dd67c   Mike Frysinger   usb: replace wait...
959
  			mdelay(100);
149dded2b   wdenk   * Add support for...
960
961
962
963
  			goto do_retry;
  		}
  		break;
  	default:
a0cb3fc31   Michael Trimarchi   USB storage clean...
964
965
966
967
968
969
  		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...
970
  			return USB_STOR_TRANSPORT_FAILED;
a0cb3fc31   Michael Trimarchi   USB storage clean...
971
  		} else
149dded2b   wdenk   * Add support for...
972
  			goto do_retry;
149dded2b   wdenk   * Add support for...
973
  		break;
affae2bff   wdenk   Initial revision
974
975
976
  	}
  	return USB_STOR_TRANSPORT_FAILED;
  }
ea7fad910   Bin Meng   dm: usb: storage:...
977
978
  static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
  				      struct us_data *us)
6158d0b42   Bin Meng   usb: storage: Ref...
979
980
  {
  	unsigned short blk;
ea7fad910   Bin Meng   dm: usb: storage:...
981
982
  	size_t __maybe_unused size;
  	int __maybe_unused ret;
6158d0b42   Bin Meng   usb: storage: Ref...
983

ea7fad910   Bin Meng   dm: usb: storage:...
984
  #ifndef CONFIG_DM_USB
6158d0b42   Bin Meng   usb: storage: Ref...
985
986
987
988
989
990
991
992
993
994
  #ifdef CONFIG_USB_EHCI_HCD
  	/*
  	 * 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.
  	 */
  	blk = USHRT_MAX;
  #else
  	blk = 20;
  #endif
ea7fad910   Bin Meng   dm: usb: storage:...
995
996
997
998
999
1000
1001
  #else
  	ret = usb_get_max_xfer_size(udev, (size_t *)&size);
  	if (ret < 0) {
  		/* unimplemented, let's use default 20 */
  		blk = 20;
  	} else {
  		if (size > USHRT_MAX * 512)
72ac8f3fc   Bin Meng   usb: storage: Fix...
1002
  			size = USHRT_MAX * 512;
ea7fad910   Bin Meng   dm: usb: storage:...
1003
1004
1005
  		blk = size / 512;
  	}
  #endif
6158d0b42   Bin Meng   usb: storage: Ref...
1006
1007
1008
  
  	us->max_xfer_blk = blk;
  }
affae2bff   wdenk   Initial revision
1009

b9560ad64   Simon Glass   dm: scsi: Drop th...
1010
  static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
1011
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1012
1013
  	int retry, i;
  	retry = 5;
affae2bff   wdenk   Initial revision
1014
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1015
1016
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_INQUIRY;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1017
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1018
1019
1020
1021
  		srb->cmd[4] = 36;
  		srb->datalen = 36;
  		srb->cmdlen = 12;
  		i = ss->transport(srb, ss);
ceb4972a8   Vivek Gautam   usb: common: Weed...
1022
1023
  		debug("inquiry returns %d
  ", i);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1024
  		if (i == 0)
affae2bff   wdenk   Initial revision
1025
  			break;
fac71cc49   Kim B. Heino   USB storage probe
1026
  	} while (--retry);
149dded2b   wdenk   * Add support for...
1027

a0cb3fc31   Michael Trimarchi   USB storage clean...
1028
  	if (!retry) {
affae2bff   wdenk   Initial revision
1029
1030
1031
1032
1033
1034
  		printf("error in inquiry
  ");
  		return -1;
  	}
  	return 0;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
1035
  static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
1036
1037
  {
  	char *ptr;
80885a9d5   wdenk   * Patch by Markus...
1038

a0cb3fc31   Michael Trimarchi   USB storage clean...
1039
1040
1041
  	ptr = (char *)srb->pdata;
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_REQ_SENSE;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1042
  	srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1043
1044
  	srb->cmd[4] = 18;
  	srb->datalen = 18;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
1045
  	srb->pdata = &srb->sense_buf[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
1046
1047
  	srb->cmdlen = 12;
  	ss->transport(srb, ss);
ceb4972a8   Vivek Gautam   usb: common: Weed...
1048
1049
1050
1051
  	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...
1052
  	srb->pdata = (uchar *)ptr;
affae2bff   wdenk   Initial revision
1053
1054
  	return 0;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
1055
  static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
1056
  {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1057
  	int retries = 10;
149dded2b   wdenk   * Add support for...
1058

affae2bff   wdenk   Initial revision
1059
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1060
1061
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_TST_U_RDY;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1062
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1063
1064
  		srb->datalen = 0;
  		srb->cmdlen = 12;
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1065
1066
  		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) {
  			ss->flags |= USB_READY;
affae2bff   wdenk   Initial revision
1067
  			return 0;
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1068
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1069
  		usb_request_sense(srb, ss);
8b57e2f08   Vincent Palatin   usb: properly det...
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  		/*
  		 * 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...
1080
  		mdelay(100);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1081
  	} while (retries--);
149dded2b   wdenk   * Add support for...
1082

affae2bff   wdenk   Initial revision
1083
1084
  	return -1;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
1085
  static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
affae2bff   wdenk   Initial revision
1086
1087
  {
  	int retry;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1088
1089
  	/* XXX retries */
  	retry = 3;
affae2bff   wdenk   Initial revision
1090
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1091
1092
  		memset(&srb->cmd[0], 0, 12);
  		srb->cmd[0] = SCSI_RD_CAPAC;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1093
  		srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1094
1095
1096
  		srb->datalen = 8;
  		srb->cmdlen = 12;
  		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
affae2bff   wdenk   Initial revision
1097
  			return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1098
  	} while (retry--);
149dded2b   wdenk   * Add support for...
1099

affae2bff   wdenk   Initial revision
1100
1101
  	return -1;
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
1102
1103
  static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
  		       unsigned long start, unsigned short blocks)
affae2bff   wdenk   Initial revision
1104
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1105
1106
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_READ10;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1107
  	srb->cmd[1] = srb->lun << 5;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1108
1109
1110
1111
1112
1113
1114
  	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...
1115
1116
  	debug("read10: start %lx blocks %x
  ", start, blocks);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1117
  	return ss->transport(srb, ss);
affae2bff   wdenk   Initial revision
1118
  }
b9560ad64   Simon Glass   dm: scsi: Drop th...
1119
1120
  static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
  			unsigned long start, unsigned short blocks)
127e10842   Mahavir Jain   usb: write comman...
1121
1122
1123
  {
  	memset(&srb->cmd[0], 0, 12);
  	srb->cmd[0] = SCSI_WRITE10;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
1124
  	srb->cmd[1] = srb->lun << 5;
127e10842   Mahavir Jain   usb: write comman...
1125
1126
1127
1128
1129
1130
1131
  	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...
1132
1133
  	debug("write10: start %lx blocks %x
  ", start, blocks);
127e10842   Mahavir Jain   usb: write comman...
1134
1135
  	return ss->transport(srb, ss);
  }
affae2bff   wdenk   Initial revision
1136

ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1137
1138
1139
1140
1141
1142
1143
1144
  #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
4101f6879   Simon Glass   dm: Drop the bloc...
1145
   * struct blk_desc in include/part.h.
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1146
1147
1148
1149
1150
1151
1152
   */
  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...
1153
1154
1155
  		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...
1156
1157
1158
  	}
  }
  #endif /* CONFIG_USB_BIN_FIXUP */
07b2b78ce   Simon Glass   dm: usb: Convert ...
1159
1160
1161
1162
  #ifdef CONFIG_BLK
  static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
  				   lbaint_t blkcnt, void *buffer)
  #else
4101f6879   Simon Glass   dm: Drop the bloc...
1163
  static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
1164
  				   lbaint_t blkcnt, void *buffer)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1165
  #endif
affae2bff   wdenk   Initial revision
1166
  {
e81e79ede   Gabe Black   usb: Support the ...
1167
1168
  	lbaint_t start, blks;
  	uintptr_t buf_addr;
affae2bff   wdenk   Initial revision
1169
  	unsigned short smallblks;
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1170
  	struct usb_device *udev;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1171
  	struct us_data *ss;
84073b6f3   Simon Glass   dm: usb: Simply d...
1172
  	int retry;
b9560ad64   Simon Glass   dm: scsi: Drop th...
1173
  	struct scsi_cmd *srb = &usb_ccb;
07b2b78ce   Simon Glass   dm: usb: Convert ...
1174
1175
1176
  #ifdef CONFIG_BLK
  	struct blk_desc *block_dev;
  #endif
f8d813e34   wdenk   * Fix SDRAM timin...
1177
1178
1179
  
  	if (blkcnt == 0)
  		return 0;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1180
  	/* Setup  device */
07b2b78ce   Simon Glass   dm: usb: Convert ...
1181
1182
1183
1184
1185
1186
1187
  #ifdef CONFIG_BLK
  	block_dev = dev_get_uclass_platdata(dev);
  	udev = dev_get_parent_priv(dev_get_parent(dev));
  	debug("
  usb_read: udev %d
  ", block_dev->devnum);
  #else
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1188
1189
1190
1191
1192
  	debug("
  usb_read: udev %d
  ", block_dev->devnum);
  	udev = usb_dev_desc[block_dev->devnum].priv;
  	if (!udev) {
84073b6f3   Simon Glass   dm: usb: Simply d...
1193
1194
1195
  		debug("%s: No device
  ", __func__);
  		return 0;
affae2bff   wdenk   Initial revision
1196
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
1197
  #endif
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1198
  	ss = (struct us_data *)udev->privptr;
affae2bff   wdenk   Initial revision
1199
1200
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1201
  	srb->lun = block_dev->lun;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1202
  	buf_addr = (uintptr_t)buffer;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1203
1204
  	start = blknr;
  	blks = blkcnt;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1205

9807c3b78   Simon Glass   dm: usb: Tidy up ...
1206
1207
1208
1209
  	debug("
  usb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
  	      PRIxPTR "
  ", block_dev->devnum, start, blks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1210

affae2bff   wdenk   Initial revision
1211
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1212
1213
1214
  		/* XXX need some comment here */
  		retry = 2;
  		srb->pdata = (unsigned char *)buf_addr;
6158d0b42   Bin Meng   usb: storage: Ref...
1215
1216
  		if (blks > ss->max_xfer_blk)
  			smallblks = ss->max_xfer_blk;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1217
1218
  		else
  			smallblks = (unsigned short) blks;
affae2bff   wdenk   Initial revision
1219
  retry_it:
6158d0b42   Bin Meng   usb: storage: Ref...
1220
  		if (smallblks == ss->max_xfer_blk)
affae2bff   wdenk   Initial revision
1221
  			usb_show_progress();
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1222
  		srb->datalen = block_dev->blksz * smallblks;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1223
  		srb->pdata = (unsigned char *)buf_addr;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1224
  		if (usb_read_10(srb, ss, start, smallblks)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1225
1226
  			debug("Read ERROR
  ");
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1227
  			usb_request_sense(srb, ss);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1228
  			if (retry--)
affae2bff   wdenk   Initial revision
1229
  				goto retry_it;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1230
  			blkcnt -= blks;
affae2bff   wdenk   Initial revision
1231
1232
  			break;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1233
1234
1235
1236
  		start += smallblks;
  		blks -= smallblks;
  		buf_addr += srb->datalen;
  	} while (blks != 0);
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1237
  	ss->flags &= ~USB_READY;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1238

ceb4972a8   Vivek Gautam   usb: common: Weed...
1239
  	debug("usb_read: end startblk " LBAF
4fd074de0   Simon Glass   usb: Use correct ...
1240
1241
  	      ", blccnt %x buffer %" PRIxPTR "
  ",
ceb4972a8   Vivek Gautam   usb: common: Weed...
1242
  	      start, smallblks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1243

affae2bff   wdenk   Initial revision
1244
  	usb_disable_asynch(0); /* asynch transfer allowed */
6158d0b42   Bin Meng   usb: storage: Ref...
1245
  	if (blkcnt >= ss->max_xfer_blk)
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
1246
1247
  		debug("
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
1248
  	return blkcnt;
affae2bff   wdenk   Initial revision
1249
  }
07b2b78ce   Simon Glass   dm: usb: Convert ...
1250
1251
1252
1253
  #ifdef CONFIG_BLK
  static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
  				    lbaint_t blkcnt, const void *buffer)
  #else
4101f6879   Simon Glass   dm: Drop the bloc...
1254
  static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
1255
  				    lbaint_t blkcnt, const void *buffer)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1256
  #endif
127e10842   Mahavir Jain   usb: write comman...
1257
  {
e81e79ede   Gabe Black   usb: Support the ...
1258
1259
  	lbaint_t start, blks;
  	uintptr_t buf_addr;
127e10842   Mahavir Jain   usb: write comman...
1260
  	unsigned short smallblks;
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1261
  	struct usb_device *udev;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1262
  	struct us_data *ss;
84073b6f3   Simon Glass   dm: usb: Simply d...
1263
  	int retry;
b9560ad64   Simon Glass   dm: scsi: Drop th...
1264
  	struct scsi_cmd *srb = &usb_ccb;
07b2b78ce   Simon Glass   dm: usb: Convert ...
1265
1266
1267
  #ifdef CONFIG_BLK
  	struct blk_desc *block_dev;
  #endif
127e10842   Mahavir Jain   usb: write comman...
1268
1269
1270
  
  	if (blkcnt == 0)
  		return 0;
127e10842   Mahavir Jain   usb: write comman...
1271
  	/* Setup  device */
07b2b78ce   Simon Glass   dm: usb: Convert ...
1272
1273
1274
1275
1276
1277
1278
  #ifdef CONFIG_BLK
  	block_dev = dev_get_uclass_platdata(dev);
  	udev = dev_get_parent_priv(dev_get_parent(dev));
  	debug("
  usb_read: udev %d
  ", block_dev->devnum);
  #else
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1279
1280
1281
1282
1283
1284
1285
  	debug("
  usb_read: udev %d
  ", block_dev->devnum);
  	udev = usb_dev_desc[block_dev->devnum].priv;
  	if (!udev) {
  		debug("%s: No device
  ", __func__);
84073b6f3   Simon Glass   dm: usb: Simply d...
1286
  		return 0;
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1287
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
1288
  #endif
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1289
  	ss = (struct us_data *)udev->privptr;
127e10842   Mahavir Jain   usb: write comman...
1290
1291
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1292
  	srb->lun = block_dev->lun;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1293
  	buf_addr = (uintptr_t)buffer;
127e10842   Mahavir Jain   usb: write comman...
1294
1295
  	start = blknr;
  	blks = blkcnt;
127e10842   Mahavir Jain   usb: write comman...
1296

9807c3b78   Simon Glass   dm: usb: Tidy up ...
1297
1298
1299
1300
  	debug("
  usb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
  	      PRIxPTR "
  ", block_dev->devnum, start, blks, buf_addr);
127e10842   Mahavir Jain   usb: write comman...
1301
1302
1303
1304
1305
1306
1307
  
  	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;
6158d0b42   Bin Meng   usb: storage: Ref...
1308
1309
  		if (blks > ss->max_xfer_blk)
  			smallblks = ss->max_xfer_blk;
127e10842   Mahavir Jain   usb: write comman...
1310
1311
1312
  		else
  			smallblks = (unsigned short) blks;
  retry_it:
6158d0b42   Bin Meng   usb: storage: Ref...
1313
  		if (smallblks == ss->max_xfer_blk)
127e10842   Mahavir Jain   usb: write comman...
1314
  			usb_show_progress();
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1315
  		srb->datalen = block_dev->blksz * smallblks;
127e10842   Mahavir Jain   usb: write comman...
1316
  		srb->pdata = (unsigned char *)buf_addr;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1317
  		if (usb_write_10(srb, ss, start, smallblks)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1318
1319
  			debug("Write ERROR
  ");
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1320
  			usb_request_sense(srb, ss);
127e10842   Mahavir Jain   usb: write comman...
1321
1322
1323
1324
1325
1326
1327
1328
1329
  			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...
1330
  	ss->flags &= ~USB_READY;
127e10842   Mahavir Jain   usb: write comman...
1331

4fd074de0   Simon Glass   usb: Use correct ...
1332
1333
1334
  	debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
  	      PRIxPTR "
  ", start, smallblks, buf_addr);
127e10842   Mahavir Jain   usb: write comman...
1335
1336
  
  	usb_disable_asynch(0); /* asynch transfer allowed */
6158d0b42   Bin Meng   usb: storage: Ref...
1337
  	if (blkcnt >= ss->max_xfer_blk)
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
1338
1339
  		debug("
  ");
127e10842   Mahavir Jain   usb: write comman...
1340
1341
1342
  	return blkcnt;
  
  }
affae2bff   wdenk   Initial revision
1343
1344
  
  /* Probe to see if a new device is actually a Storage device */
a0cb3fc31   Michael Trimarchi   USB storage clean...
1345
1346
  int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
  		      struct us_data *ss)
affae2bff   wdenk   Initial revision
1347
  {
8f8bd565f   Tom Rix   USB Consolidate d...
1348
  	struct usb_interface *iface;
affae2bff   wdenk   Initial revision
1349
  	int i;
605bd75af   Vivek Gautam   USB: Some cleanup...
1350
  	struct usb_endpoint_descriptor *ep_desc;
affae2bff   wdenk   Initial revision
1351
  	unsigned int flags = 0;
affae2bff   wdenk   Initial revision
1352
1353
  	/* let's examine the device now */
  	iface = &dev->config.if_desc[ifnum];
affae2bff   wdenk   Initial revision
1354
  	if (dev->descriptor.bDeviceClass != 0 ||
8f8bd565f   Tom Rix   USB Consolidate d...
1355
1356
1357
  			iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
  			iface->desc.bInterfaceSubClass < US_SC_MIN ||
  			iface->desc.bInterfaceSubClass > US_SC_MAX) {
1d5827a12   Simon Glass   dm: usb: Fix type...
1358
1359
  		debug("Not mass storage
  ");
affae2bff   wdenk   Initial revision
1360
1361
1362
  		/* if it's not a mass storage, we go no further */
  		return 0;
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1363
  	memset(ss, 0, sizeof(struct us_data));
affae2bff   wdenk   Initial revision
1364
  	/* At this point, we know we've got a live one */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1365
1366
1367
1368
  	debug("
  
  USB Mass Storage device detected
  ");
affae2bff   wdenk   Initial revision
1369
1370
1371
1372
1373
1374
  
  	/* Initialize the us_data structure with some useful info */
  	ss->flags = flags;
  	ss->ifnum = ifnum;
  	ss->pusb_dev = dev;
  	ss->attention_done = 0;
f5fb78a27   Tom Rini   common/usb_storag...
1375
1376
  	ss->subclass = iface->desc.bInterfaceSubClass;
  	ss->protocol = iface->desc.bInterfaceProtocol;
affae2bff   wdenk   Initial revision
1377
1378
  
  	/* set the handler pointers based on the protocol */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1379
  	debug("Transport: ");
affae2bff   wdenk   Initial revision
1380
1381
  	switch (ss->protocol) {
  	case US_PR_CB:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1382
1383
  		debug("Control/Bulk
  ");
affae2bff   wdenk   Initial revision
1384
1385
1386
1387
1388
  		ss->transport = usb_stor_CB_transport;
  		ss->transport_reset = usb_stor_CB_reset;
  		break;
  
  	case US_PR_CBI:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1389
1390
  		debug("Control/Bulk/Interrupt
  ");
affae2bff   wdenk   Initial revision
1391
1392
1393
  		ss->transport = usb_stor_CB_transport;
  		ss->transport_reset = usb_stor_CB_reset;
  		break;
149dded2b   wdenk   * Add support for...
1394
  	case US_PR_BULK:
ceb4972a8   Vivek Gautam   usb: common: Weed...
1395
1396
  		debug("Bulk/Bulk/Bulk
  ");
149dded2b   wdenk   * Add support for...
1397
1398
1399
  		ss->transport = usb_stor_BBB_transport;
  		ss->transport_reset = usb_stor_BBB_reset;
  		break;
affae2bff   wdenk   Initial revision
1400
  	default:
80885a9d5   wdenk   * Patch by Markus...
1401
1402
  		printf("USB Storage Transport unknown / not yet implemented
  ");
affae2bff   wdenk   Initial revision
1403
1404
1405
1406
1407
1408
1409
1410
1411
  		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...
1412
  	for (i = 0; i < iface->desc.bNumEndpoints; i++) {
605bd75af   Vivek Gautam   USB: Some cleanup...
1413
  		ep_desc = &iface->ep_desc[i];
affae2bff   wdenk   Initial revision
1414
  		/* is it an BULK endpoint? */
605bd75af   Vivek Gautam   USB: Some cleanup...
1415
  		if ((ep_desc->bmAttributes &
a0cb3fc31   Michael Trimarchi   USB storage clean...
1416
  		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
605bd75af   Vivek Gautam   USB: Some cleanup...
1417
1418
1419
  			if (ep_desc->bEndpointAddress & USB_DIR_IN)
  				ss->ep_in = ep_desc->bEndpointAddress &
  						USB_ENDPOINT_NUMBER_MASK;
affae2bff   wdenk   Initial revision
1420
  			else
a0cb3fc31   Michael Trimarchi   USB storage clean...
1421
  				ss->ep_out =
605bd75af   Vivek Gautam   USB: Some cleanup...
1422
  					ep_desc->bEndpointAddress &
affae2bff   wdenk   Initial revision
1423
1424
1425
1426
  					USB_ENDPOINT_NUMBER_MASK;
  		}
  
  		/* is it an interrupt endpoint? */
605bd75af   Vivek Gautam   USB: Some cleanup...
1427
1428
1429
1430
1431
  		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
1432
1433
  		}
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
1434
1435
1436
  	debug("Endpoints In %d Out %d Int %d
  ",
  	      ss->ep_in, ss->ep_out, ss->ep_int);
affae2bff   wdenk   Initial revision
1437
1438
  
  	/* Do some basic sanity checks, and bail if we find a problem */
8f8bd565f   Tom Rix   USB Consolidate d...
1439
  	if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
affae2bff   wdenk   Initial revision
1440
1441
  	    !ss->ep_in || !ss->ep_out ||
  	    (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1442
1443
  		debug("Problems with device
  ");
affae2bff   wdenk   Initial revision
1444
1445
1446
  		return 0;
  	}
  	/* set class specific stuff */
149dded2b   wdenk   * Add support for...
1447
1448
  	/* We only handle certain protocols.  Currently, these are
  	 * the only ones.
80885a9d5   wdenk   * Patch by Markus...
1449
  	 * The SFF8070 accepts the requests used in u-boot
affae2bff   wdenk   Initial revision
1450
  	 */
80885a9d5   wdenk   * Patch by Markus...
1451
1452
  	if (ss->subclass != US_SC_UFI && ss->subclass != US_SC_SCSI &&
  	    ss->subclass != US_SC_8070) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1453
1454
  		printf("Sorry, protocol %d not yet supported.
  ", ss->subclass);
affae2bff   wdenk   Initial revision
1455
1456
  		return 0;
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1457
1458
1459
1460
  	if (ss->ep_int) {
  		/* we had found an interrupt endpoint, prepare irq pipe
  		 * set up the IRQ pipe and handler
  		 */
affae2bff   wdenk   Initial revision
1461
1462
1463
  		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...
1464
  		dev->irq_handle = usb_stor_irq;
affae2bff   wdenk   Initial revision
1465
  	}
6158d0b42   Bin Meng   usb: storage: Ref...
1466
1467
  
  	/* Set the maximum transfer size per host controller setting */
ea7fad910   Bin Meng   dm: usb: storage:...
1468
  	usb_stor_set_max_xfer_blk(dev, ss);
6158d0b42   Bin Meng   usb: storage: Ref...
1469

a0cb3fc31   Michael Trimarchi   USB storage clean...
1470
  	dev->privptr = (void *)ss;
affae2bff   wdenk   Initial revision
1471
1472
  	return 1;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
1473
  int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
4101f6879   Simon Glass   dm: Drop the bloc...
1474
  		      struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
1475
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1476
  	unsigned char perq, modi;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1477
1478
1479
  	ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
  	ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
  	u32 capacity, blksz;
b9560ad64   Simon Glass   dm: scsi: Drop th...
1480
  	struct scsi_cmd *pccb = &usb_ccb;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1481

9c998aa83   Wolfgang Denk   Fix low-level OHC...
1482
1483
1484
1485
  	pccb->pdata = usb_stor_buf;
  
  	dev_desc->target = dev->devnum;
  	pccb->lun = dev_desc->lun;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1486
1487
  	debug(" address %d
  ", dev_desc->target);
affae2bff   wdenk   Initial revision
1488

1d5827a12   Simon Glass   dm: usb: Fix type...
1489
1490
1491
  	if (usb_inquiry(pccb, ss)) {
  		debug("%s: usb_inquiry() failed
  ", __func__);
affae2bff   wdenk   Initial revision
1492
  		return -1;
1d5827a12   Simon Glass   dm: usb: Fix type...
1493
  	}
095b8a379   Wolfgang Denk   Coding style cleanup
1494

9c998aa83   Wolfgang Denk   Fix low-level OHC...
1495
1496
  	perq = usb_stor_buf[0];
  	modi = usb_stor_buf[1];
a0cb3fc31   Michael Trimarchi   USB storage clean...
1497

6a559bbe2   Soeren Moch   usb_storage: blac...
1498
1499
1500
1501
1502
  	/*
  	 * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
  	 * they would not respond to test_unit_ready .
  	 */
  	if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
1d5827a12   Simon Glass   dm: usb: Fix type...
1503
1504
  		debug("%s: unknown/unsupported device
  ", __func__);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1505
  		return 0;
affae2bff   wdenk   Initial revision
1506
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1507
1508
  	if ((modi&0x80) == 0x80) {
  		/* drive is removable */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1509
  		dev_desc->removable = 1;
affae2bff   wdenk   Initial revision
1510
  	}
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1511
1512
1513
  	memcpy(dev_desc->vendor, (const void *)&usb_stor_buf[8], 8);
  	memcpy(dev_desc->product, (const void *)&usb_stor_buf[16], 16);
  	memcpy(dev_desc->revision, (const void *)&usb_stor_buf[32], 4);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1514
1515
1516
  	dev_desc->vendor[8] = 0;
  	dev_desc->product[16] = 0;
  	dev_desc->revision[4] = 0;
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1517
  #ifdef CONFIG_USB_BIN_FIXUP
a0cb3fc31   Michael Trimarchi   USB storage clean...
1518
1519
  	usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
  		      (uchar *)dev_desc->product);
ddde6b7cf   Bartlomiej Sieka   Add a fix for a b...
1520
  #endif /* CONFIG_USB_BIN_FIXUP */
ceb4972a8   Vivek Gautam   usb: common: Weed...
1521
1522
1523
  	debug("ISO Vers %X, Response Data %X
  ", usb_stor_buf[2],
  	      usb_stor_buf[3]);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1524
1525
1526
1527
1528
1529
1530
  	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]);
1e5eca7d4   Troy Kisky   usb: return 0 fro...
1531
  		if (dev_desc->removable == 1)
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1532
  			dev_desc->type = perq;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1533
  		return 0;
affae2bff   wdenk   Initial revision
1534
  	}
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1535
  	pccb->pdata = (unsigned char *)cap;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1536
1537
  	memset(pccb->pdata, 0, 8);
  	if (usb_read_capacity(pccb, ss) != 0) {
affae2bff   wdenk   Initial revision
1538
1539
  		printf("READ_CAP ERROR
  ");
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1540
1541
  		cap[0] = 2880;
  		cap[1] = 0x200;
affae2bff   wdenk   Initial revision
1542
  	}
3e8581bb9   Benoît Thébaudeau   usb_stor_BBB_tran...
1543
  	ss->flags &= ~USB_READY;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1544
1545
  	debug("Read Capacity returns: 0x%08x, 0x%08x
  ", cap[0], cap[1]);
affae2bff   wdenk   Initial revision
1546
  #if 0
a0cb3fc31   Michael Trimarchi   USB storage clean...
1547
1548
  	if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
  		cap[0] >>= 16;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1549

c918261c6   Christian Eggers   USB: replace old ...
1550
1551
  	cap[0] = cpu_to_be32(cap[0]);
  	cap[1] = cpu_to_be32(cap[1]);
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1552
1553
1554
1555
  #endif
  
  	capacity = be32_to_cpu(cap[0]) + 1;
  	blksz = be32_to_cpu(cap[1]);
c918261c6   Christian Eggers   USB: replace old ...
1556

f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1557
1558
1559
1560
  	debug("Capacity = 0x%08x, blocksz = 0x%08x
  ", capacity, blksz);
  	dev_desc->lba = capacity;
  	dev_desc->blksz = blksz;
0472fbfd3   Egbert Eich   part/dev_desc: Ad...
1561
  	dev_desc->log2blksz = LOG2(dev_desc->blksz);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1562
  	dev_desc->type = perq;
ceb4972a8   Vivek Gautam   usb: common: Weed...
1563
1564
  	debug(" address %d
  ", dev_desc->target);
affae2bff   wdenk   Initial revision
1565

affae2bff   wdenk   Initial revision
1566
1567
  	return 1;
  }
acf277af6   Simon Glass   dm: usb: Convert ...
1568
1569
1570
1571
1572
  
  #ifdef CONFIG_DM_USB
  
  static int usb_mass_storage_probe(struct udevice *dev)
  {
bcbe3d157   Simon Glass   dm: Rename dev_ge...
1573
  	struct usb_device *udev = dev_get_parent_priv(dev);
acf277af6   Simon Glass   dm: usb: Convert ...
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
  	int ret;
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
  	ret = usb_stor_probe_device(udev);
  	usb_disable_asynch(0); /* asynch transfer allowed */
  
  	return ret;
  }
  
  static const struct udevice_id usb_mass_storage_ids[] = {
  	{ .compatible = "usb-mass-storage" },
  	{ }
  };
  
  U_BOOT_DRIVER(usb_mass_storage) = {
  	.name	= "usb_mass_storage",
  	.id	= UCLASS_MASS_STORAGE,
  	.of_match = usb_mass_storage_ids,
  	.probe = usb_mass_storage_probe,
07b2b78ce   Simon Glass   dm: usb: Convert ...
1593
1594
1595
  #ifdef CONFIG_BLK
  	.platdata_auto_alloc_size	= sizeof(struct us_data),
  #endif
acf277af6   Simon Glass   dm: usb: Convert ...
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
  };
  
  UCLASS_DRIVER(usb_mass_storage) = {
  	.id		= UCLASS_MASS_STORAGE,
  	.name		= "usb_mass_storage",
  };
  
  static const struct usb_device_id mass_storage_id_table[] = {
  	{
  		.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
  		.bInterfaceClass = USB_CLASS_MASS_STORAGE
  	},
  	{ }		/* Terminating entry */
  };
abb59cffc   Simon Glass   dm: usb: Adjust t...
1610
  U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
07b2b78ce   Simon Glass   dm: usb: Convert ...
1611
  #endif
acf277af6   Simon Glass   dm: usb: Convert ...
1612

07b2b78ce   Simon Glass   dm: usb: Convert ...
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
  #ifdef CONFIG_BLK
  static const struct blk_ops usb_storage_ops = {
  	.read	= usb_stor_read,
  	.write	= usb_stor_write,
  };
  
  U_BOOT_DRIVER(usb_storage_blk) = {
  	.name		= "usb_storage_blk",
  	.id		= UCLASS_BLK,
  	.ops		= &usb_storage_ops,
  };
c0543bf6b   Simon Glass   dm: usb: Add a le...
1624
1625
1626
1627
1628
1629
1630
  #else
  U_BOOT_LEGACY_BLK(usb) = {
  	.if_typename	= "usb",
  	.if_type	= IF_TYPE_USB,
  	.max_devs	= USB_MAX_STOR_DEV,
  	.desc		= usb_dev_desc,
  };
acf277af6   Simon Glass   dm: usb: Convert ...
1631
  #endif