*
* Adapted for U-Boot:
* (C) Copyright 2001 Denis Peter, MPL AG Switzerland
+ * Driver model conversion:
+ * (C) Copyright 2015 Google, Inc
*
* For BBB support (C) Copyright 2003
* Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
* BBB support based on /sys/dev/usb/umass.c from
* FreeBSD.
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
+ * SPDX-License-Identifier: GPL-2.0+
*/
/* Note:
#include <common.h>
#include <command.h>
+#include <dm.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <mapmem.h>
#include <asm/byteorder.h>
#include <asm/processor.h>
+#include <dm/device-internal.h>
#include <part.h>
#include <usb.h>
#undef BBB_COMDAT_TRACE
#undef BBB_XPORT_TRACE
-#ifdef USB_STOR_DEBUG
-#define USB_BLK_DEBUG 1
-#else
-#define USB_BLK_DEBUG 0
-#endif
-
-#define USB_STOR_PRINTF(fmt, args...) debug_cond(USB_BLK_DEBUG, fmt, ##args)
-
#include <scsi.h>
/* direction table -- this indicates the direction of the data
* transfer for each command code -- a 1 indicates input
#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
-
-/*
- * CBI style
- */
-
-#define US_CBI_ADSC 0
-
-/*
- * BULK only
- */
-#define US_BBB_RESET 0xff
-#define US_BBB_GET_MAX_LUN 0xfe
-
-/* Command Block Wrapper */
-typedef struct {
- __u32 dCBWSignature;
-# define CBWSIGNATURE 0x43425355
- __u32 dCBWTag;
- __u32 dCBWDataTransferLength;
- __u8 bCBWFlags;
-# define CBWFLAGS_OUT 0x00
-# define CBWFLAGS_IN 0x80
- __u8 bCBWLUN;
- __u8 bCDBLength;
-# define CBWCDBLENGTH 16
- __u8 CBWCDB[CBWCDBLENGTH];
-} umass_bbb_cbw_t;
-#define UMASS_BBB_CBW_SIZE 31
static __u32 CBWTag;
-/* Command Status Wrapper */
-typedef struct {
- __u32 dCSWSignature;
-# define CSWSIGNATURE 0x53425355
- __u32 dCSWTag;
- __u32 dCSWDataResidue;
- __u8 bCSWStatus;
-# define CSWSTATUS_GOOD 0x0
-# define CSWSTATUS_FAILED 0x1
-# define CSWSTATUS_PHASE 0x2
-} umass_bbb_csw_t;
-#define UMASS_BBB_CSW_SIZE 13
-
#define USB_MAX_STOR_DEV 5
static int usb_max_devs; /* number of highest available usb device */
static struct us_data usb_stor[USB_MAX_STOR_DEV];
-
#define USB_STOR_TRANSPORT_GOOD 0
#define USB_STOR_TRANSPORT_FAILED -1
#define USB_STOR_TRANSPORT_ERROR -2
block_dev_desc_t *dev_desc);
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
struct us_data *ss);
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
lbaint_t blkcnt, void *buffer);
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
lbaint_t blkcnt, const void *buffer);
-struct usb_device * usb_get_dev_index(int index);
void uhci_show_temp_int_td(void);
#ifdef CONFIG_PARTITIONS
0, us->ifnum,
result, sizeof(char),
USB_CNTL_TIMEOUT * 5);
- USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
- len, (int) *result);
+ debug("Get Max LUN -> len = %i, result = %i\n", len, (int) *result);
return (len > 0) ? *result : 0;
}
+static int usb_stor_probe_device(struct usb_device *dev)
+{
+ if (dev == NULL)
+ return -ENOENT; /* no more devices available */
+
+ debug("\n\nProbing for storage\n");
+ if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
+ /* OK, it's a storage device. Iterate over its LUNs
+ * and populate `usb_dev_desc'.
+ */
+ int lun, max_lun, start = usb_max_devs;
+
+ max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
+ for (lun = 0;
+ lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
+ lun++) {
+ struct block_dev_desc *blkdev;
+
+ blkdev = &usb_dev_desc[usb_max_devs];
+ memset(blkdev, '\0', sizeof(block_dev_desc_t));
+ blkdev->if_type = IF_TYPE_USB;
+ blkdev->dev = 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 = dev;
+
+ if (usb_stor_get_info(dev, &usb_stor[start],
+ &usb_dev_desc[usb_max_devs]) ==
+ 1) {
+ usb_max_devs++;
+ debug("%s: Found device %p\n", __func__, dev);
+ }
+ }
+ }
+
+ /* if storage device */
+ if (usb_max_devs == USB_MAX_STOR_DEV) {
+ printf("max USB Storage Device reached: %d stopping\n",
+ usb_max_devs);
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+void usb_stor_reset(void)
+{
+ usb_max_devs = 0;
+}
+
+#ifndef CONFIG_DM_USB
/*******************************************************************************
* scan the usb and reports device info
* to the user if mode = 1
int usb_stor_scan(int mode)
{
unsigned char i;
- struct usb_device *dev;
if (mode == 1)
printf(" scanning usb for storage devices... ");
usb_disable_asynch(1); /* asynch transfer not allowed */
- for (i = 0; i < USB_MAX_STOR_DEV; i++) {
- memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t));
- usb_dev_desc[i].if_type = IF_TYPE_USB;
- usb_dev_desc[i].dev = i;
- usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
- usb_dev_desc[i].target = 0xff;
- usb_dev_desc[i].type = DEV_TYPE_UNKNOWN;
- usb_dev_desc[i].block_read = usb_stor_read;
- usb_dev_desc[i].block_write = usb_stor_write;
- }
-
- usb_max_devs = 0;
+ usb_stor_reset();
for (i = 0; i < USB_MAX_DEVICE; i++) {
+ struct usb_device *dev;
+
dev = usb_get_dev_index(i); /* get device */
- USB_STOR_PRINTF("i=%d\n", i);
- if (dev == NULL)
- break; /* no more devices available */
-
- if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
- /* OK, it's a storage device. Iterate over its LUNs
- * and populate `usb_dev_desc'.
- */
- int lun, max_lun, start = usb_max_devs;
-
- max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
- for (lun = 0;
- lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
- lun++) {
- usb_dev_desc[usb_max_devs].lun = lun;
- if (usb_stor_get_info(dev, &usb_stor[start],
- &usb_dev_desc[usb_max_devs]) == 1) {
- usb_max_devs++;
- }
- }
- }
- /* if storage device */
- if (usb_max_devs == USB_MAX_STOR_DEV) {
- printf("max USB Storage Device reached: %d stopping\n",
- usb_max_devs);
+ debug("i=%d\n", i);
+ if (usb_stor_probe_device(dev))
break;
- }
} /* for */
usb_disable_asynch(0); /* asynch transfer allowed */
return 0;
return -1;
}
+#endif
static int usb_stor_irq(struct usb_device *dev)
{
}
-#ifdef USB_STOR_DEBUG
+#ifdef DEBUG
static void usb_show_srb(ccb *pccb)
{
/* set up the transfer loop */
do {
/* transfer the data */
- USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
- (unsigned int)buf, this_xfer, 11 - maxtry);
+ debug("Bulk xfer 0x%lx(%d) try #%d\n",
+ (ulong)map_to_sysmem(buf), this_xfer,
+ 11 - maxtry);
result = usb_bulk_msg(us->pusb_dev, pipe, buf,
this_xfer, &partial,
USB_CNTL_TIMEOUT * 5);
- USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
- result, partial, this_xfer);
+ debug("bulk_msg returned %d xferred %d/%d\n",
+ result, partial, this_xfer);
if (us->pusb_dev->status != 0) {
/* if we stall, we need to clear it before
* we go on
*/
-#ifdef USB_STOR_DEBUG
+#ifdef DEBUG
display_int_status(us->pusb_dev->status);
#endif
if (us->pusb_dev->status & USB_ST_STALLED) {
- USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
+ debug("stalled ->clearing endpoint" \
+ "halt for pipe 0x%x\n", pipe);
stat = us->pusb_dev->status;
usb_clear_halt(us->pusb_dev, pipe);
us->pusb_dev->status = stat;
if (this_xfer == partial) {
- USB_STOR_PRINTF("bulk transferred with error %lX, but data ok\n", us->pusb_dev->status);
+ debug("bulk transferred" \
+ "with error %lX," \
+ " but data ok\n",
+ us->pusb_dev->status);
return 0;
}
else
return result;
}
if (us->pusb_dev->status & USB_ST_NAK_REC) {
- USB_STOR_PRINTF("Device NAKed bulk_msg\n");
+ debug("Device NAKed bulk_msg\n");
return result;
}
- USB_STOR_PRINTF("bulk transferred with error");
+ debug("bulk transferred with error");
if (this_xfer == partial) {
- USB_STOR_PRINTF(" %ld, but data ok\n",
- us->pusb_dev->status);
+ debug(" %ld, but data ok\n",
+ us->pusb_dev->status);
return 0;
}
/* if our try counter reaches 0, bail out */
- USB_STOR_PRINTF(" %ld, data %d\n",
- us->pusb_dev->status, partial);
+ debug(" %ld, data %d\n",
+ us->pusb_dev->status, partial);
if (!maxtry--)
return result;
}
*
* This comment stolen from FreeBSD's /sys/dev/usb/umass.c.
*/
- USB_STOR_PRINTF("BBB_reset\n");
+ debug("BBB_reset\n");
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
US_BBB_RESET,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, NULL, 0, USB_CNTL_TIMEOUT * 5);
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
- USB_STOR_PRINTF("RESET:stall\n");
+ debug("RESET:stall\n");
return -1;
}
/* long wait for reset */
mdelay(150);
- USB_STOR_PRINTF("BBB_reset result %d: status %lX reset\n", result,
- us->pusb_dev->status);
+ debug("BBB_reset result %d: status %lX reset\n",
+ result, us->pusb_dev->status);
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
result = usb_clear_halt(us->pusb_dev, pipe);
/* long wait for reset */
mdelay(150);
- USB_STOR_PRINTF("BBB_reset result %d: status %lX clearing IN endpoint\n",
- result, us->pusb_dev->status);
+ debug("BBB_reset result %d: status %lX clearing IN endpoint\n",
+ result, us->pusb_dev->status);
/* long wait for reset */
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
result = usb_clear_halt(us->pusb_dev, pipe);
mdelay(150);
- USB_STOR_PRINTF("BBB_reset result %d: status %lX"
- " clearing OUT endpoint\n", result,
- us->pusb_dev->status);
- USB_STOR_PRINTF("BBB_reset done\n");
+ debug("BBB_reset result %d: status %lX clearing OUT endpoint\n",
+ result, us->pusb_dev->status);
+ debug("BBB_reset done\n");
return 0;
}
unsigned char cmd[12];
int result;
- USB_STOR_PRINTF("CB_reset\n");
+ debug("CB_reset\n");
memset(cmd, 0xff, sizeof(cmd));
cmd[0] = SCSI_SEND_DIAG;
cmd[1] = 4;
/* long wait for reset */
mdelay(1500);
- USB_STOR_PRINTF("CB_reset result %d: status %lX"
- " clearing endpoint halt\n", result,
- us->pusb_dev->status);
+ debug("CB_reset result %d: status %lX clearing endpoint halt\n",
+ result, us->pusb_dev->status);
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));
- USB_STOR_PRINTF("CB_reset done\n");
+ debug("CB_reset done\n");
return 0;
}
int actlen;
int dir_in;
unsigned int pipe;
- ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
+ ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_cbw, cbw, 1);
dir_in = US_DIRECTION(srb->cmd[0]);
#ifdef BBB_COMDAT_TRACE
- printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
+ printf("dir %d lun %d cmdlen %d cmd %p datalen %lu pdata %p\n",
dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
srb->pdata);
if (srb->cmdlen) {
#endif
/* sanity checks */
if (!(srb->cmdlen <= CBWCDBLENGTH)) {
- USB_STOR_PRINTF("usb_stor_BBB_comdat:cmdlen too large\n");
+ debug("usb_stor_BBB_comdat:cmdlen too large\n");
return -1;
}
cbw->bCDBLength = srb->cmdlen;
/* copy the command data into the CBW command data buffer */
/* DST SRC LEN!!! */
+
memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
&actlen, USB_CNTL_TIMEOUT * 5);
if (result < 0)
- USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
+ debug("usb_stor_BBB_comdat:usb_bulk_msg error\n");
return result;
}
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
while (retry--) {
- USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
-#ifdef USB_STOR_DEBUG
+ debug("CBI gets a command: Try %d\n", 5 - retry);
+#ifdef DEBUG
usb_show_srb(srb);
#endif
/* let's send the command via the control pipe */
0, us->ifnum,
srb->cmd, srb->cmdlen,
USB_CNTL_TIMEOUT * 5);
- USB_STOR_PRINTF("CB_transport: control msg returned %d,"
- " status %lX\n", result, us->pusb_dev->status);
+ debug("CB_transport: control msg returned %d, status %lX\n",
+ result, us->pusb_dev->status);
/* check the return code for the command */
if (result < 0) {
if (us->pusb_dev->status & USB_ST_STALLED) {
status = us->pusb_dev->status;
- USB_STOR_PRINTF(" stall during command found,"
- " clear pipe\n");
+ debug(" stall during command found," \
+ " clear pipe\n");
usb_clear_halt(us->pusb_dev,
usb_sndctrlpipe(us->pusb_dev, 0));
us->pusb_dev->status = status;
}
- USB_STOR_PRINTF(" error during command %02X"
- " Stat = %lX\n", srb->cmd[0],
- us->pusb_dev->status);
+ debug(" error during command %02X" \
+ " Stat = %lX\n", srb->cmd[0],
+ us->pusb_dev->status);
return result;
}
/* transfer the data payload for this command, if one exists*/
- USB_STOR_PRINTF("CB_transport: control msg returned %d,"
- " direction is %s to go 0x%lx\n", result,
- dir_in ? "IN" : "OUT", srb->datalen);
+ debug("CB_transport: control msg returned %d," \
+ " direction is %s to go 0x%lx\n", result,
+ dir_in ? "IN" : "OUT", srb->datalen);
if (srb->datalen) {
result = us_one_transfer(us, pipe, (char *)srb->pdata,
srb->datalen);
- USB_STOR_PRINTF("CBI attempted to transfer data,"
- " result is %d status %lX, len %d\n",
- result, us->pusb_dev->status,
- us->pusb_dev->act_len);
+ debug("CBI attempted to transfer data," \
+ " result is %d status %lX, len %d\n",
+ result, us->pusb_dev->status,
+ us->pusb_dev->act_len);
if (!(us->pusb_dev->status & USB_ST_NAK_REC))
break;
} /* if (srb->datalen) */
(void *) &us->ip_data, us->irqmaxp, us->irqinterval);
timeout = 1000;
while (timeout--) {
- if ((volatile int *) us->ip_wanted == NULL)
+ if (us->ip_wanted == 0)
break;
mdelay(10);
}
us->ip_wanted = 0;
return USB_STOR_TRANSPORT_ERROR;
}
- USB_STOR_PRINTF
- ("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
- us->ip_data, us->pusb_dev->irq_act_len,
- us->pusb_dev->irq_status);
+ debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
+ us->ip_data, us->pusb_dev->irq_act_len,
+ us->pusb_dev->irq_status);
/* UFI gives us ASC and ASCQ, like a request sense */
if (us->subclass == US_SC_UFI) {
if (srb->cmd[0] == SCSI_REQ_SENSE ||
int dir_in;
int actlen, data_actlen;
unsigned int pipe, pipein, pipeout;
- ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
+ ALLOC_CACHE_ALIGN_BUFFER(struct umass_bbb_csw, csw, 1);
#ifdef BBB_XPORT_TRACE
unsigned char *ptr;
int index;
dir_in = US_DIRECTION(srb->cmd[0]);
/* COMMAND phase */
- USB_STOR_PRINTF("COMMAND phase\n");
+ debug("COMMAND phase\n");
result = usb_stor_BBB_comdat(srb, us);
if (result < 0) {
- USB_STOR_PRINTF("failed to send CBW status %ld\n",
- us->pusb_dev->status);
+ debug("failed to send CBW status %ld\n",
+ us->pusb_dev->status);
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
}
/* no data, go immediately to the STATUS phase */
if (srb->datalen == 0)
goto st;
- USB_STOR_PRINTF("DATA phase\n");
+ debug("DATA phase\n");
if (dir_in)
pipe = pipein;
else
pipe = pipeout;
+
result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
&data_actlen, USB_CNTL_TIMEOUT * 5);
/* special handling of STALL in DATA phase */
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
- USB_STOR_PRINTF("DATA:stall\n");
+ debug("DATA:stall\n");
/* clear the STALL on the endpoint */
result = usb_stor_BBB_clear_endpt_stall(us,
dir_in ? us->ep_in : us->ep_out);
goto st;
}
if (result < 0) {
- USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
- us->pusb_dev->status);
+ debug("usb_bulk_msg error status %ld\n",
+ us->pusb_dev->status);
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
}
st:
retry = 0;
again:
- USB_STOR_PRINTF("STATUS phase\n");
+ debug("STATUS phase\n");
result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
&actlen, USB_CNTL_TIMEOUT*5);
/* special handling of STALL in STATUS phase */
if ((result < 0) && (retry < 1) &&
(us->pusb_dev->status & USB_ST_STALLED)) {
- USB_STOR_PRINTF("STATUS:stall\n");
+ debug("STATUS:stall\n");
/* clear the STALL on the endpoint */
result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
if (result >= 0 && (retry++ < 1))
goto again;
}
if (result < 0) {
- USB_STOR_PRINTF("usb_bulk_msg error status %ld\n",
- us->pusb_dev->status);
+ debug("usb_bulk_msg error status %ld\n",
+ us->pusb_dev->status);
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
}
if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
pipe = srb->datalen - data_actlen;
if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
- USB_STOR_PRINTF("!CSWSIGNATURE\n");
+ debug("!CSWSIGNATURE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
- USB_STOR_PRINTF("!Tag\n");
+ debug("!Tag\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
- USB_STOR_PRINTF(">PHASE\n");
+ debug(">PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
- USB_STOR_PRINTF("=PHASE\n");
+ debug("=PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if (data_actlen > srb->datalen) {
- USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
- data_actlen, srb->datalen);
+ debug("transferred %dB instead of %ldB\n",
+ data_actlen, srb->datalen);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
- USB_STOR_PRINTF("FAILED\n");
+ debug("FAILED\n");
return USB_STOR_TRANSPORT_FAILED;
}
/* issue the command */
do_retry:
result = usb_stor_CB_comdat(srb, us);
- USB_STOR_PRINTF("command / Data returned %d, status %lX\n",
- result, us->pusb_dev->status);
+ debug("command / Data returned %d, status %lX\n",
+ result, us->pusb_dev->status);
/* if this is an CBI Protocol, get IRQ */
if (us->protocol == US_PR_CBI) {
status = usb_stor_CBI_get_status(srb, us);
/* if the status is error, report it */
if (status == USB_STOR_TRANSPORT_ERROR) {
- USB_STOR_PRINTF(" USB CBI Command Error\n");
+ debug(" USB CBI Command Error\n");
return status;
}
srb->sense_buf[12] = (unsigned char)(us->ip_data >> 8);
if (!us->ip_data) {
/* if the status is good, report it */
if (status == USB_STOR_TRANSPORT_GOOD) {
- USB_STOR_PRINTF(" USB CBI Command Good\n");
+ debug(" USB CBI Command Good\n");
return status;
}
}
/* do we have to issue an auto request? */
/* HERE we have to check the result */
if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
- USB_STOR_PRINTF("ERROR %lX\n", us->pusb_dev->status);
+ debug("ERROR %lX\n", us->pusb_dev->status);
us->transport_reset(us);
return USB_STOR_TRANSPORT_ERROR;
}
((srb->cmd[0] == SCSI_REQ_SENSE) ||
(srb->cmd[0] == SCSI_INQUIRY))) {
/* do not issue an autorequest after request sense */
- USB_STOR_PRINTF("No auto request and good\n");
+ debug("No auto request and good\n");
return USB_STOR_TRANSPORT_GOOD;
}
/* issue an request_sense */
psrb->cmdlen = 12;
/* issue the command */
result = usb_stor_CB_comdat(psrb, us);
- USB_STOR_PRINTF("auto request returned %d\n", result);
+ debug("auto request returned %d\n", result);
/* if this is an CBI Protocol, get IRQ */
if (us->protocol == US_PR_CBI)
status = usb_stor_CBI_get_status(psrb, us);
if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
- USB_STOR_PRINTF(" AUTO REQUEST ERROR %ld\n",
- us->pusb_dev->status);
+ debug(" AUTO REQUEST ERROR %ld\n",
+ us->pusb_dev->status);
return USB_STOR_TRANSPORT_ERROR;
}
- USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
- srb->sense_buf[0], srb->sense_buf[2],
- srb->sense_buf[12], srb->sense_buf[13]);
+ debug("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ srb->sense_buf[0], srb->sense_buf[2],
+ srb->sense_buf[12], srb->sense_buf[13]);
/* Check the auto request result */
if ((srb->sense_buf[2] == 0) &&
(srb->sense_buf[12] == 0) &&
srb->datalen = 36;
srb->cmdlen = 12;
i = ss->transport(srb, ss);
- USB_STOR_PRINTF("inquiry returns %d\n", i);
+ debug("inquiry returns %d\n", i);
if (i == 0)
break;
} while (--retry);
srb->pdata = &srb->sense_buf[0];
srb->cmdlen = 12;
ss->transport(srb, ss);
- USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
- srb->sense_buf[2], srb->sense_buf[12],
- srb->sense_buf[13]);
+ debug("Request Sense returned %02X %02X %02X\n",
+ srb->sense_buf[2], srb->sense_buf[12],
+ srb->sense_buf[13]);
srb->pdata = (uchar *)ptr;
return 0;
}
return 0;
}
usb_request_sense(srb, ss);
+ /*
+ * 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;
mdelay(100);
} while (retries--);
srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
srb->cmd[8] = (unsigned char) blocks & 0xff;
srb->cmdlen = 12;
- USB_STOR_PRINTF("read10: start %lx blocks %x\n", start, blocks);
+ debug("read10: start %lx blocks %x\n", start, blocks);
return ss->transport(srb, ss);
}
srb->cmd[7] = ((unsigned char) (blocks >> 8)) & 0xff;
srb->cmd[8] = (unsigned char) blocks & 0xff;
srb->cmdlen = 12;
- USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
+ debug("write10: start %lx blocks %x\n", start, blocks);
return ss->transport(srb, ss);
}
}
#endif /* CONFIG_USB_BIN_FIXUP */
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
lbaint_t blkcnt, void *buffer)
{
lbaint_t start, blks;
unsigned short smallblks;
struct usb_device *dev;
struct us_data *ss;
- int retry, i;
+ int retry;
ccb *srb = &usb_ccb;
if (blkcnt == 0)
device &= 0xff;
/* Setup device */
- USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
- dev = NULL;
- for (i = 0; i < USB_MAX_DEVICE; i++) {
- dev = usb_get_dev_index(i);
- if (dev == NULL)
- return 0;
- if (dev->devnum == usb_dev_desc[device].target)
- break;
+ debug("\nusb_read: dev %d\n", device);
+ dev = usb_dev_desc[device].priv;
+ if (!dev) {
+ debug("%s: No device\n", __func__);
+ return 0;
}
ss = (struct us_data *)dev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
srb->lun = usb_dev_desc[device].lun;
- buf_addr = (unsigned long)buffer;
+ buf_addr = (uintptr_t)buffer;
start = blknr;
blks = blkcnt;
- USB_STOR_PRINTF("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
- " buffer %lx\n", device, start, blks, buf_addr);
+ debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
+ " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
do {
/* XXX need some comment here */
srb->datalen = usb_dev_desc[device].blksz * smallblks;
srb->pdata = (unsigned char *)buf_addr;
if (usb_read_10(srb, ss, start, smallblks)) {
- USB_STOR_PRINTF("Read ERROR\n");
+ debug("Read ERROR\n");
usb_request_sense(srb, ss);
if (retry--)
goto retry_it;
} while (blks != 0);
ss->flags &= ~USB_READY;
- USB_STOR_PRINTF("usb_read: end startblk " LBAF
- ", blccnt %x buffer %lx\n",
- start, smallblks, buf_addr);
+ debug("usb_read: end startblk " LBAF
+ ", blccnt %x buffer %" PRIxPTR "\n",
+ start, smallblks, buf_addr);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= USB_MAX_XFER_BLK)
return blkcnt;
}
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
lbaint_t blkcnt, const void *buffer)
{
lbaint_t start, blks;
unsigned short smallblks;
struct usb_device *dev;
struct us_data *ss;
- int retry, i;
+ int retry;
ccb *srb = &usb_ccb;
if (blkcnt == 0)
device &= 0xff;
/* Setup device */
- USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
- dev = NULL;
- for (i = 0; i < USB_MAX_DEVICE; i++) {
- dev = usb_get_dev_index(i);
- if (dev == NULL)
- return 0;
- if (dev->devnum == usb_dev_desc[device].target)
- break;
- }
+ debug("\nusb_write: dev %d\n", device);
+ dev = usb_dev_desc[device].priv;
+ if (!dev)
+ return 0;
ss = (struct us_data *)dev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
srb->lun = usb_dev_desc[device].lun;
- buf_addr = (unsigned long)buffer;
+ buf_addr = (uintptr_t)buffer;
start = blknr;
blks = blkcnt;
- USB_STOR_PRINTF("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
- " buffer %lx\n", device, start, blks, buf_addr);
+ debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
+ " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
do {
/* If write fails retry for max retry count else
srb->datalen = usb_dev_desc[device].blksz * smallblks;
srb->pdata = (unsigned char *)buf_addr;
if (usb_write_10(srb, ss, start, smallblks)) {
- USB_STOR_PRINTF("Write ERROR\n");
+ debug("Write ERROR\n");
usb_request_sense(srb, ss);
if (retry--)
goto retry_it;
} while (blks != 0);
ss->flags &= ~USB_READY;
- USB_STOR_PRINTF("usb_write: end startblk " LBAF
- ", blccnt %x buffer %lx\n",
- start, smallblks, buf_addr);
+ debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
+ PRIxPTR "\n", start, smallblks, buf_addr);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= USB_MAX_XFER_BLK)
{
struct usb_interface *iface;
int i;
+ struct usb_endpoint_descriptor *ep_desc;
unsigned int flags = 0;
int protocol = 0;
#if 0
/* this is the place to patch some storage devices */
- USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
+ debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
dev->descriptor.idProduct);
if ((dev->descriptor.idVendor) == 0x066b &&
(dev->descriptor.idProduct) == 0x0103) {
- USB_STOR_PRINTF("patched for E-USB\n");
+ debug("patched for E-USB\n");
protocol = US_PR_CB;
subclass = US_SC_UFI; /* an assumption */
}
iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
iface->desc.bInterfaceSubClass < US_SC_MIN ||
iface->desc.bInterfaceSubClass > US_SC_MAX) {
+ debug("Not mass storage\n");
/* if it's not a mass storage, we go no further */
return 0;
}
memset(ss, 0, sizeof(struct us_data));
/* At this point, we know we've got a live one */
- USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
+ debug("\n\nUSB Mass Storage device detected\n");
/* Initialize the us_data structure with some useful info */
ss->flags = flags;
}
/* set the handler pointers based on the protocol */
- USB_STOR_PRINTF("Transport: ");
+ debug("Transport: ");
switch (ss->protocol) {
case US_PR_CB:
- USB_STOR_PRINTF("Control/Bulk\n");
+ debug("Control/Bulk\n");
ss->transport = usb_stor_CB_transport;
ss->transport_reset = usb_stor_CB_reset;
break;
case US_PR_CBI:
- USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
+ debug("Control/Bulk/Interrupt\n");
ss->transport = usb_stor_CB_transport;
ss->transport_reset = usb_stor_CB_reset;
break;
case US_PR_BULK:
- USB_STOR_PRINTF("Bulk/Bulk/Bulk\n");
+ debug("Bulk/Bulk/Bulk\n");
ss->transport = usb_stor_BBB_transport;
ss->transport_reset = usb_stor_BBB_reset;
break;
* We will ignore any others.
*/
for (i = 0; i < iface->desc.bNumEndpoints; i++) {
+ ep_desc = &iface->ep_desc[i];
/* is it an BULK endpoint? */
- if ((iface->ep_desc[i].bmAttributes &
+ if ((ep_desc->bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
- if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
- ss->ep_in = iface->ep_desc[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ if (ep_desc->bEndpointAddress & USB_DIR_IN)
+ ss->ep_in = ep_desc->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
else
ss->ep_out =
- iface->ep_desc[i].bEndpointAddress &
+ ep_desc->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
}
/* is it an interrupt endpoint? */
- if ((iface->ep_desc[i].bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
- ss->ep_int = iface->ep_desc[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- ss->irqinterval = iface->ep_desc[i].bInterval;
+ 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;
}
}
- USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
- ss->ep_in, ss->ep_out, ss->ep_int);
+ debug("Endpoints In %d Out %d Int %d\n",
+ ss->ep_in, ss->ep_out, ss->ep_int);
/* Do some basic sanity checks, and bail if we find a problem */
if (usb_set_interface(dev, iface->desc.bInterfaceNumber, 0) ||
!ss->ep_in || !ss->ep_out ||
(ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
- USB_STOR_PRINTF("Problems with device\n");
+ debug("Problems with device\n");
return 0;
}
/* set class specific stuff */
block_dev_desc_t *dev_desc)
{
unsigned char perq, modi;
- ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
- ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
- unsigned long *capacity, *blksz;
+ ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
+ ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
+ u32 capacity, blksz;
ccb *pccb = &usb_ccb;
pccb->pdata = usb_stor_buf;
dev_desc->target = dev->devnum;
pccb->lun = dev_desc->lun;
- USB_STOR_PRINTF(" address %d\n", dev_desc->target);
+ debug(" address %d\n", dev_desc->target);
- if (usb_inquiry(pccb, ss))
+ if (usb_inquiry(pccb, ss)) {
+ debug("%s: usb_inquiry() failed\n", __func__);
return -1;
+ }
perq = usb_stor_buf[0];
modi = usb_stor_buf[1];
- if ((perq & 0x1f) == 0x1f) {
- /* skip unknown devices */
+ /*
+ * Skip unknown devices (0x1f) and enclosure service devices (0x0d),
+ * they would not respond to test_unit_ready .
+ */
+ if (((perq & 0x1f) == 0x1f) || ((perq & 0x1f) == 0x0d)) {
+ debug("%s: unknown/unsupported device\n", __func__);
return 0;
}
if ((modi&0x80) == 0x80) {
/* drive is removable */
dev_desc->removable = 1;
}
- memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
- memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
- memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
+ 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);
dev_desc->vendor[8] = 0;
dev_desc->product[16] = 0;
dev_desc->revision[4] = 0;
usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor,
(uchar *)dev_desc->product);
#endif /* CONFIG_USB_BIN_FIXUP */
- USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
- usb_stor_buf[3]);
+ debug("ISO Vers %X, Response Data %X\n", usb_stor_buf[2],
+ usb_stor_buf[3]);
if (usb_test_unit_ready(pccb, ss)) {
printf("Device NOT ready\n"
" Request Sense returned %02X %02X %02X\n",
}
return 0;
}
- pccb->pdata = (unsigned char *)&cap[0];
+ pccb->pdata = (unsigned char *)cap;
memset(pccb->pdata, 0, 8);
if (usb_read_capacity(pccb, ss) != 0) {
printf("READ_CAP ERROR\n");
cap[1] = 0x200;
}
ss->flags &= ~USB_READY;
- USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
- cap[1]);
+ debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
#if 0
if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
cap[0] >>= 16;
-#endif
+
cap[0] = cpu_to_be32(cap[0]);
cap[1] = cpu_to_be32(cap[1]);
+#endif
+
+ capacity = be32_to_cpu(cap[0]) + 1;
+ blksz = be32_to_cpu(cap[1]);
- /* this assumes bigendian! */
- cap[0] += 1;
- capacity = &cap[0];
- blksz = &cap[1];
- USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
- *capacity, *blksz);
- dev_desc->lba = *capacity;
- dev_desc->blksz = *blksz;
+ debug("Capacity = 0x%08x, blocksz = 0x%08x\n", capacity, blksz);
+ dev_desc->lba = capacity;
+ dev_desc->blksz = blksz;
+ dev_desc->log2blksz = LOG2(dev_desc->blksz);
dev_desc->type = perq;
- USB_STOR_PRINTF(" address %d\n", dev_desc->target);
- USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
+ debug(" address %d\n", dev_desc->target);
+ debug("partype: %d\n", dev_desc->part_type);
init_part(dev_desc);
- USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);
+ debug("partype: %d\n", dev_desc->part_type);
return 1;
}
+
+#ifdef CONFIG_DM_USB
+
+static int usb_mass_storage_probe(struct udevice *dev)
+{
+ struct usb_device *udev = dev_get_parentdata(dev);
+ 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,
+};
+
+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 */
+};
+
+U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
+
+#endif