Blame view

common/usb_storage.c 42.1 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;
a0cb3fc31   Michael Trimarchi   USB storage clean...
666
  	submit_int_msg(us->pusb_dev, us->irqpipe,
80885a9d5   wdenk   * Patch by Markus...
667
668
669
  			(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
  	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
976
  {
  	unsigned short blk;
ea7fad910   Bin Meng   dm: usb: storage:...
977
978
  	size_t __maybe_unused size;
  	int __maybe_unused ret;
6158d0b42   Bin Meng   usb: storage: Ref...
979

fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
980
  #if !CONFIG_IS_ENABLED(DM_USB)
6158d0b42   Bin Meng   usb: storage: Ref...
981
982
983
984
985
986
  #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.
  	 */
032b2e0dc   Peng Fan   MLK-12883 usb: li...
987
  	blk = 256;
6158d0b42   Bin Meng   usb: storage: Ref...
988
989
990
  #else
  	blk = 20;
  #endif
ea7fad910   Bin Meng   dm: usb: storage:...
991
992
993
994
995
996
  #else
  	ret = usb_get_max_xfer_size(udev, (size_t *)&size);
  	if (ret < 0) {
  		/* unimplemented, let's use default 20 */
  		blk = 20;
  	} else {
032b2e0dc   Peng Fan   MLK-12883 usb: li...
997
998
  		if (size > 256 * 512)
  			size = 256 * 512;
ea7fad910   Bin Meng   dm: usb: storage:...
999
1000
1001
  		blk = size / 512;
  	}
  #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 */
9807c3b78   Simon Glass   dm: usb: Tidy up ...
1197
  	srb->lun = block_dev->lun;
f65708713   Sergey Temerkhanov   usb_storage:Fix U...
1198
  	buf_addr = (uintptr_t)buffer;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1199
1200
  	start = blknr;
  	blks = blkcnt;
a0cb3fc31   Michael Trimarchi   USB storage clean...
1201

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

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

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

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

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

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

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

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

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

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

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

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

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

affae2bff   wdenk   Initial revision
1561
1562
  	return 1;
  }
acf277af6   Simon Glass   dm: usb: Convert ...
1563

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

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