Blame view

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

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

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

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

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

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

80885a9d5   wdenk   * Patch by Markus...
102
  #define USB_STOR_TRANSPORT_GOOD	   0
affae2bff   wdenk   Initial revision
103
104
  #define USB_STOR_TRANSPORT_FAILED -1
  #define USB_STOR_TRANSPORT_ERROR  -2
a0cb3fc31   Michael Trimarchi   USB storage clean...
105
  int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
4101f6879   Simon Glass   dm: Drop the bloc...
106
  		      struct blk_desc *dev_desc);
a0cb3fc31   Michael Trimarchi   USB storage clean...
107
108
  int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
  		      struct us_data *ss);
1af9bfd33   Sven Schwermer   usb: storage: s/C...
109
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
110
111
112
113
114
  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...
115
  static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
116
  				   lbaint_t blkcnt, void *buffer);
4101f6879   Simon Glass   dm: Drop the bloc...
117
  static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
118
  				    lbaint_t blkcnt, const void *buffer);
07b2b78ce   Simon Glass   dm: usb: Convert ...
119
  #endif
affae2bff   wdenk   Initial revision
120
  void uhci_show_temp_int_td(void);
199adb601   Kim Phillips   common/misc: spar...
121
  static void usb_show_progress(void)
affae2bff   wdenk   Initial revision
122
  {
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
123
  	debug(".");
affae2bff   wdenk   Initial revision
124
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
125
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
126
127
128
   * 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 ...
129
  int usb_stor_info(void)
9c998aa83   Wolfgang Denk   Fix low-level OHC...
130
  {
9807c3b78   Simon Glass   dm: usb: Tidy up ...
131
  	int count = 0;
1af9bfd33   Sven Schwermer   usb: storage: s/C...
132
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
133
134
135
136
137
138
139
140
141
142
143
144
  	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...
145
  	int i;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
146
  	if (usb_max_devs > 0) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
147
  		for (i = 0; i < usb_max_devs; i++) {
a0cb3fc31   Michael Trimarchi   USB storage clean...
148
  			printf("  Device %d: ", i);
9c998aa83   Wolfgang Denk   Fix low-level OHC...
149
150
  			dev_print(&usb_dev_desc[i]);
  		}
b9e749e95   Markus Klotzbuecher   USB, Storage: fix...
151
  		return 0;
f6b44e0e4   Aras Vaichas   USB Storage, add ...
152
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
153
  #endif
9807c3b78   Simon Glass   dm: usb: Tidy up ...
154
155
156
157
158
  	if (!count) {
  		printf("No storage devices, perhaps not 'usb start'ed..?
  ");
  		return 1;
  	}
b94fc8518   Simon Glass   usb: Correct retu...
159
  	return 0;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
160
  }
99e9ed1f4   Ludovic Courtès   usb: Add support ...
161
162
163
  static unsigned int usb_get_max_lun(struct us_data *us)
  {
  	int len;
f57661394   Puneet Saxena   USB: Align buffer...
164
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
99e9ed1f4   Ludovic Courtès   usb: Add support ...
165
166
167
168
169
  	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...
170
  			      result, sizeof(char),
99e9ed1f4   Ludovic Courtès   usb: Add support ...
171
  			      USB_CNTL_TIMEOUT * 5);
ceb4972a8   Vivek Gautam   usb: common: Weed...
172
173
  	debug("Get Max LUN -> len = %i, result = %i
  ", len, (int) *result);
f57661394   Puneet Saxena   USB: Align buffer...
174
  	return (len > 0) ? *result : 0;
99e9ed1f4   Ludovic Courtès   usb: Add support ...
175
  }
9807c3b78   Simon Glass   dm: usb: Tidy up ...
176
  static int usb_stor_probe_device(struct usb_device *udev)
91557579a   Simon Glass   dm: usb: Move sto...
177
  {
9807c3b78   Simon Glass   dm: usb: Tidy up ...
178
  	int lun, max_lun;
07b2b78ce   Simon Glass   dm: usb: Convert ...
179

1af9bfd33   Sven Schwermer   usb: storage: s/C...
180
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
181
  	struct us_data *data;
07b2b78ce   Simon Glass   dm: usb: Convert ...
182
183
  	int ret;
  #else
9807c3b78   Simon Glass   dm: usb: Tidy up ...
184
185
186
  	int start;
  
  	if (udev == NULL)
91557579a   Simon Glass   dm: usb: Move sto...
187
  		return -ENOENT; /* no more devices available */
07b2b78ce   Simon Glass   dm: usb: Convert ...
188
189
190
191
192
193
  #endif
  
  	debug("
  
  Probing for storage
  ");
1af9bfd33   Sven Schwermer   usb: storage: s/C...
194
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
195
196
197
198
199
200
201
202
203
204
205
206
  	/*
  	 * 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...
207
  		char str[10];
07b2b78ce   Simon Glass   dm: usb: Convert ...
208

9107c973d   Simon Glass   dm: blk: Add a ea...
209
210
211
212
  		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 ...
213
214
215
216
217
218
219
220
221
  		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...
222

07b2b78ce   Simon Glass   dm: usb: Convert ...
223
  		ret = usb_stor_get_info(udev, data, blkdev);
d0851c893   Bin Meng   blk: Call part_in...
224
  		if (ret == 1) {
07b2b78ce   Simon Glass   dm: usb: Convert ...
225
226
227
228
229
230
231
232
233
234
235
236
  			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...
237
238
239
240
241
242
243
  	/* 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 ...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  	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 ...
272
273
274
275
276
  			debug("partype: %d
  ", blkdev->part_type);
  			part_init(blkdev);
  			debug("partype: %d
  ", blkdev->part_type);
9807c3b78   Simon Glass   dm: usb: Tidy up ...
277
278
279
  			usb_max_devs++;
  			debug("%s: Found device %p
  ", __func__, udev);
91557579a   Simon Glass   dm: usb: Move sto...
280
281
  		}
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
282
  #endif
91557579a   Simon Glass   dm: usb: Move sto...
283

91557579a   Simon Glass   dm: usb: Move sto...
284
285
286
287
288
289
290
  	return 0;
  }
  
  void usb_stor_reset(void)
  {
  	usb_max_devs = 0;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
291
  /*******************************************************************************
9c998aa83   Wolfgang Denk   Fix low-level OHC...
292
   * scan the usb and reports device info
affae2bff   wdenk   Initial revision
293
294
295
296
297
   * 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...
298
  	if (mode == 1)
93c2582fe   Lucas Stach   usb: add support ...
299
  		printf("       scanning usb for storage devices... ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
300

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

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

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

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

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

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

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

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

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

d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
860
  	psrb = &reqsrb;
a0cb3fc31   Michael Trimarchi   USB storage clean...
861
862
863
  	status = USB_STOR_TRANSPORT_GOOD;
  	retry = 0;
  	notready = 0;
affae2bff   wdenk   Initial revision
864
865
  	/* issue the command */
  do_retry:
a0cb3fc31   Michael Trimarchi   USB storage clean...
866
  	result = usb_stor_CB_comdat(srb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
867
868
869
  	debug("command / Data returned %d, status %lX
  ",
  	      result, us->pusb_dev->status);
affae2bff   wdenk   Initial revision
870
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
871
872
  	if (us->protocol == US_PR_CBI) {
  		status = usb_stor_CBI_get_status(srb, us);
affae2bff   wdenk   Initial revision
873
  		/* if the status is error, report it */
a0cb3fc31   Michael Trimarchi   USB storage clean...
874
  		if (status == USB_STOR_TRANSPORT_ERROR) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
875
876
  			debug(" USB CBI Command Error
  ");
affae2bff   wdenk   Initial revision
877
878
  			return status;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
879
880
881
882
883
  		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...
884
885
  				debug(" USB CBI Command Good
  ");
affae2bff   wdenk   Initial revision
886
887
888
889
890
891
  				return status;
  			}
  		}
  	}
  	/* do we have to issue an auto request? */
  	/* HERE we have to check the result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
892
  	if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
893
894
  		debug("ERROR %lX
  ", us->pusb_dev->status);
affae2bff   wdenk   Initial revision
895
896
897
  		us->transport_reset(us);
  		return USB_STOR_TRANSPORT_ERROR;
  	}
a0cb3fc31   Michael Trimarchi   USB storage clean...
898
899
900
901
  	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...
902
903
  		debug("No auto request and good
  ");
affae2bff   wdenk   Initial revision
904
905
906
  		return USB_STOR_TRANSPORT_GOOD;
  	}
  	/* issue an request_sense */
a0cb3fc31   Michael Trimarchi   USB storage clean...
907
908
909
910
911
  	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...
912
  	psrb->pdata = &srb->sense_buf[0];
a0cb3fc31   Michael Trimarchi   USB storage clean...
913
  	psrb->cmdlen = 12;
affae2bff   wdenk   Initial revision
914
  	/* issue the command */
a0cb3fc31   Michael Trimarchi   USB storage clean...
915
  	result = usb_stor_CB_comdat(psrb, us);
ceb4972a8   Vivek Gautam   usb: common: Weed...
916
917
  	debug("auto request returned %d
  ", result);
affae2bff   wdenk   Initial revision
918
  	/* if this is an CBI Protocol, get IRQ */
a0cb3fc31   Michael Trimarchi   USB storage clean...
919
920
921
922
  	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...
923
924
925
  		debug(" AUTO REQUEST ERROR %ld
  ",
  		      us->pusb_dev->status);
affae2bff   wdenk   Initial revision
926
927
  		return USB_STOR_TRANSPORT_ERROR;
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
928
929
930
931
  	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
932
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
933
934
935
936
  	if ((srb->sense_buf[2] == 0) &&
  	    (srb->sense_buf[12] == 0) &&
  	    (srb->sense_buf[13] == 0)) {
  		/* ok, no sense */
affae2bff   wdenk   Initial revision
937
  		return USB_STOR_TRANSPORT_GOOD;
a0cb3fc31   Michael Trimarchi   USB storage clean...
938
  	}
affae2bff   wdenk   Initial revision
939
  	/* Check the auto request result */
a0cb3fc31   Michael Trimarchi   USB storage clean...
940
941
942
  	switch (srb->sense_buf[2]) {
  	case 0x01:
  		/* Recovered Error */
149dded2b   wdenk   * Add support for...
943
  		return USB_STOR_TRANSPORT_GOOD;
80885a9d5   wdenk   * Patch by Markus...
944
  		break;
a0cb3fc31   Michael Trimarchi   USB storage clean...
945
946
947
948
949
950
951
952
  	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...
953
954
  			return USB_STOR_TRANSPORT_FAILED;
  		} else {
5b84dd67c   Mike Frysinger   usb: replace wait...
955
  			mdelay(100);
149dded2b   wdenk   * Add support for...
956
957
958
959
  			goto do_retry;
  		}
  		break;
  	default:
a0cb3fc31   Michael Trimarchi   USB storage clean...
960
961
962
963
964
965
  		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...
966
  			return USB_STOR_TRANSPORT_FAILED;
a0cb3fc31   Michael Trimarchi   USB storage clean...
967
  		} else
149dded2b   wdenk   * Add support for...
968
  			goto do_retry;
149dded2b   wdenk   * Add support for...
969
  		break;
affae2bff   wdenk   Initial revision
970
971
972
  	}
  	return USB_STOR_TRANSPORT_FAILED;
  }
ea7fad910   Bin Meng   dm: usb: storage:...
973
974
  static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
  				      struct us_data *us)
6158d0b42   Bin Meng   usb: storage: Ref...
975
  {
6158d0b42   Bin Meng   usb: storage: Ref...
976
  	/*
7d6fd7f0b   Marek Vasut   usb: storage: Lim...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
  	 * Limit the total size of a transfer to 120 KB.
  	 *
  	 * Some devices are known to choke with anything larger. It seems like
  	 * the problem stems from the fact that original IDE controllers had
  	 * only an 8-bit register to hold the number of sectors in one transfer
  	 * and even those couldn't handle a full 256 sectors.
  	 *
  	 * Because we want to make sure we interoperate with as many devices as
  	 * possible, we will maintain a 240 sector transfer size limit for USB
  	 * Mass Storage devices.
  	 *
  	 * Tests show that other operating have similar limits with Microsoft
  	 * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
  	 * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
  	 * and 2048 for USB3 devices.
6158d0b42   Bin Meng   usb: storage: Ref...
992
  	 */
7d6fd7f0b   Marek Vasut   usb: storage: Lim...
993
994
995
996
997
  	unsigned short blk = 240;
  
  #if CONFIG_IS_ENABLED(DM_USB)
  	size_t size;
  	int ret;
ea7fad910   Bin Meng   dm: usb: storage:...
998
  	ret = usb_get_max_xfer_size(udev, (size_t *)&size);
7d6fd7f0b   Marek Vasut   usb: storage: Lim...
999
  	if ((ret >= 0) && (size < blk * 512))
ea7fad910   Bin Meng   dm: usb: storage:...
1000
  		blk = size / 512;
ea7fad910   Bin Meng   dm: usb: storage:...
1001
  #endif
6158d0b42   Bin Meng   usb: storage: Ref...
1002
1003
1004
  
  	us->max_xfer_blk = blk;
  }
affae2bff   wdenk   Initial revision
1005

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

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

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

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

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

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

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

dee37fc99   Masahiro Yamada   Remove <inttypes....
1203
1204
1205
1206
  	debug("
  usb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx
  ",
  	      block_dev->devnum, start, blks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1207

affae2bff   wdenk   Initial revision
1208
  	do {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1209
1210
1211
  		/* XXX need some comment here */
  		retry = 2;
  		srb->pdata = (unsigned char *)buf_addr;
6158d0b42   Bin Meng   usb: storage: Ref...
1212
1213
  		if (blks > ss->max_xfer_blk)
  			smallblks = ss->max_xfer_blk;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1214
1215
  		else
  			smallblks = (unsigned short) blks;
affae2bff   wdenk   Initial revision
1216
  retry_it:
6158d0b42   Bin Meng   usb: storage: Ref...
1217
  		if (smallblks == ss->max_xfer_blk)
affae2bff   wdenk   Initial revision
1218
  			usb_show_progress();
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1219
  		srb->datalen = block_dev->blksz * smallblks;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1220
  		srb->pdata = (unsigned char *)buf_addr;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1221
  		if (usb_read_10(srb, ss, start, smallblks)) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
1222
1223
  			debug("Read ERROR
  ");
da3d1c499   Marek Vasut   usb: storage: Onl...
1224
  			ss->flags &= ~USB_READY;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1225
  			usb_request_sense(srb, ss);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1226
  			if (retry--)
affae2bff   wdenk   Initial revision
1227
  				goto retry_it;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1228
  			blkcnt -= blks;
affae2bff   wdenk   Initial revision
1229
1230
  			break;
  		}
a0cb3fc31   Michael Trimarchi   USB storage clean...
1231
1232
1233
1234
  		start += smallblks;
  		blks -= smallblks;
  		buf_addr += srb->datalen;
  	} while (blks != 0);
dee37fc99   Masahiro Yamada   Remove <inttypes....
1235
1236
  	debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx
  ",
ceb4972a8   Vivek Gautam   usb: common: Weed...
1237
  	      start, smallblks, buf_addr);
a0cb3fc31   Michael Trimarchi   USB storage clean...
1238

31232de07   Marek Vasut   usb: Keep async s...
1239
  	usb_lock_async(udev, 0);
affae2bff   wdenk   Initial revision
1240
  	usb_disable_asynch(0); /* asynch transfer allowed */
6158d0b42   Bin Meng   usb: storage: Ref...
1241
  	if (blkcnt >= ss->max_xfer_blk)
226fa9bb9   Wolfgang Denk   usb_storage.c: ch...
1242
1243
  		debug("
  ");
a0cb3fc31   Michael Trimarchi   USB storage clean...
1244
  	return blkcnt;
affae2bff   wdenk   Initial revision
1245
  }
1af9bfd33   Sven Schwermer   usb: storage: s/C...
1246
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1247
1248
1249
  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...
1250
  static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
7c4213f6a   Stephen Warren   block: pass block...
1251
  				    lbaint_t blkcnt, const void *buffer)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1252
  #endif
127e10842   Mahavir Jain   usb: write comman...
1253
  {
e81e79ede   Gabe Black   usb: Support the ...
1254
1255
  	lbaint_t start, blks;
  	uintptr_t buf_addr;
127e10842   Mahavir Jain   usb: write comman...
1256
  	unsigned short smallblks;
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1257
  	struct usb_device *udev;
5dd95cf93   Kyle Moffett   usb_storage: Fix ...
1258
  	struct us_data *ss;
84073b6f3   Simon Glass   dm: usb: Simply d...
1259
  	int retry;
b9560ad64   Simon Glass   dm: scsi: Drop th...
1260
  	struct scsi_cmd *srb = &usb_ccb;
1af9bfd33   Sven Schwermer   usb: storage: s/C...
1261
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1262
1263
  	struct blk_desc *block_dev;
  #endif
127e10842   Mahavir Jain   usb: write comman...
1264
1265
1266
  
  	if (blkcnt == 0)
  		return 0;
127e10842   Mahavir Jain   usb: write comman...
1267
  	/* Setup  device */
1af9bfd33   Sven Schwermer   usb: storage: s/C...
1268
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1269
1270
1271
1272
1273
1274
  	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 ...
1275
1276
1277
1278
1279
1280
1281
  	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...
1282
  		return 0;
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1283
  	}
07b2b78ce   Simon Glass   dm: usb: Convert ...
1284
  #endif
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1285
  	ss = (struct us_data *)udev->privptr;
127e10842   Mahavir Jain   usb: write comman...
1286
1287
  
  	usb_disable_asynch(1); /* asynch transfer not allowed */
31232de07   Marek Vasut   usb: Keep async s...
1288
  	usb_lock_async(udev, 1);
127e10842   Mahavir Jain   usb: write comman...
1289

9807c3b78   Simon Glass   dm: usb: Tidy up ...
1290
  	srb->lun = block_dev->lun;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1291
  	buf_addr = (uintptr_t)buffer;
127e10842   Mahavir Jain   usb: write comman...
1292
1293
  	start = blknr;
  	blks = blkcnt;
127e10842   Mahavir Jain   usb: write comman...
1294

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

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

a0cb3fc31   Michael Trimarchi   USB storage clean...
1468
  	dev->privptr = (void *)ss;
affae2bff   wdenk   Initial revision
1469
1470
  	return 1;
  }
a0cb3fc31   Michael Trimarchi   USB storage clean...
1471
  int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
4101f6879   Simon Glass   dm: Drop the bloc...
1472
  		      struct blk_desc *dev_desc)
affae2bff   wdenk   Initial revision
1473
  {
a0cb3fc31   Michael Trimarchi   USB storage clean...
1474
  	unsigned char perq, modi;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1475
1476
1477
  	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...
1478
  	struct scsi_cmd *pccb = &usb_ccb;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1479

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

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

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

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

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

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

affae2bff   wdenk   Initial revision
1564
1565
  	return 1;
  }
acf277af6   Simon Glass   dm: usb: Convert ...
1566

fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
1567
  #if CONFIG_IS_ENABLED(DM_USB)
acf277af6   Simon Glass   dm: usb: Convert ...
1568
1569
1570
  
  static int usb_mass_storage_probe(struct udevice *dev)
  {
bcbe3d157   Simon Glass   dm: Rename dev_ge...
1571
  	struct usb_device *udev = dev_get_parent_priv(dev);
acf277af6   Simon Glass   dm: usb: Convert ...
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
  	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,
1af9bfd33   Sven Schwermer   usb: storage: s/C...
1591
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1592
1593
  	.platdata_auto_alloc_size	= sizeof(struct us_data),
  #endif
acf277af6   Simon Glass   dm: usb: Convert ...
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
  };
  
  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...
1608
  U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
07b2b78ce   Simon Glass   dm: usb: Convert ...
1609
  #endif
acf277af6   Simon Glass   dm: usb: Convert ...
1610

1af9bfd33   Sven Schwermer   usb: storage: s/C...
1611
  #if CONFIG_IS_ENABLED(BLK)
07b2b78ce   Simon Glass   dm: usb: Convert ...
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
  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...
1622
1623
1624
1625
1626
1627
1628
  #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 ...
1629
  #endif