summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-04-09 12:24:49 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-04-09 12:24:49 +0200
commit383b3cb658f99f3fd9aea3fe94e9060e895a7568 (patch)
tree4418324917cc79ee911c542485340ce1cddeccd6 /drivers
parent731cc538f3bdce594095d31af9bc288dcd511ab9 (diff)
parent3f4dfa9077cb189da4895e9408e8556adec69b26 (diff)
downloadbarebox-383b3cb658f99f3fd9aea3fe94e9060e895a7568.tar.gz
barebox-383b3cb658f99f3fd9aea3fe94e9060e895a7568.tar.xz
Merge branch 'for-next/usb-storage'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c1
-rw-r--r--drivers/usb/core/hub.c1
-rw-r--r--drivers/usb/core/usb.c24
-rw-r--r--drivers/usb/storage/transport.c87
-rw-r--r--drivers/usb/storage/transport.h2
-rw-r--r--drivers/usb/storage/usb.c484
-rw-r--r--drivers/usb/storage/usb.h19
7 files changed, 265 insertions, 353 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b416105970..e6723a337c 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -27,7 +27,6 @@
#include <io.h>
#include <of.h>
#include <malloc.h>
-#include <scsi.h>
#include <linux/ctype.h>
#include <linux/err.h>
#include <disks.h>
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 39e5fe67d4..d01a016077 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -21,7 +21,6 @@
#include <init.h>
#include <malloc.h>
#include <errno.h>
-#include <scsi.h>
#include <usb/phy.h>
#include <usb/usb.h>
#include <usb/usb_defs.h>
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 7b008435fd..d29cd1328b 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -63,7 +63,6 @@
static int dev_count;
static int dev_index;
-static int asynch_allowed;
static LIST_HEAD(host_list);
LIST_HEAD(usb_device_list);
@@ -98,7 +97,6 @@ int usb_register_host(struct usb_host *host)
list_add_tail(&host->list, &host_list);
host->busnum = host_busnum++;
host->sem = 0;
- asynch_allowed = 1;
return 0;
}
@@ -559,16 +557,6 @@ void usb_rescan(void)
pr_info("%d USB Device(s) found\n", dev_count);
}
-/*
- * disables the asynch behaviour of the control message. This is used for data
- * transfers that uses the exclusiv access to the control and bulk messages.
- */
-void usb_disable_asynch(int disable)
-{
- asynch_allowed = !disable;
-}
-
-
/*-------------------------------------------------------------------
* Message wrappers.
*
@@ -597,10 +585,9 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
/*
* submits a control message and waits for completion (at least timeout * 1ms)
* If timeout is 0, we don't wait for completion (used as example to set and
- * clear keyboards LEDs). For data transfers, (storage transfers) we don't
- * allow control messages with 0 timeout, by previously resetting the flag
- * asynch_allowed (usb_disable_asynch(1)).
- * returns the transfered length if OK or -1 if error. The transfered length
+ * clear keyboards LEDs).
+ *
+ * Returns the transfered length if OK or -1 if error. The transfered length
* and the current status are stored in the dev->act_len and dev->status.
*/
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
@@ -612,11 +599,6 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
int ret;
struct devrequest *setup_packet = dev->setup_packet;
- if ((timeout == 0) && (!asynch_allowed)) {
- /* request for a asynch control pipe is not allowed */
- return -1;
- }
-
ret = usb_host_acquire(host);
if (ret)
return ret;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 4140991340..48ccee2072 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -24,8 +24,6 @@
#include <errno.h>
#include <dma.h>
-#undef USB_STOR_DEBUG
-
#include "usb.h"
#include "transport.h"
@@ -62,6 +60,7 @@ static int usb_stor_Bulk_clear_endpt_stall(struct us_data *us, unsigned int pipe
/* Determine what the maximum LUN supported is */
int usb_stor_Bulk_max_lun(struct us_data *us)
{
+ struct device_d *dev = &us->pusb_dev->dev;
int len, ret = 0;
unsigned char *iobuf = dma_alloc(1);
@@ -73,8 +72,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, iobuf, 1, USB_CNTL_TIMEOUT);
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- len, (int)iobuf[0]);
+ dev_dbg(dev, "GetMaxLUN command result is %d, data is %d\n",
+ len, (int)iobuf[0]);
/* if we have a successful request, return the result */
if (len > 0)
@@ -92,8 +91,12 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
return ret;
}
-int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
+int usb_stor_Bulk_transport(struct us_blk_dev *usb_blkdev,
+ const u8 *cmd, u8 cmdlen,
+ void *data, u32 datalen)
{
+ struct us_data *us = usb_blkdev->us;
+ struct device_d *dev = &us->pusb_dev->dev;
struct bulk_cb_wrap cbw;
struct bulk_cs_wrap csw;
int actlen, data_actlen;
@@ -101,30 +104,28 @@ int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
unsigned int residue;
unsigned int pipein = usb_rcvbulkpipe(us->pusb_dev, us->recv_bulk_ep);
unsigned int pipeout = usb_sndbulkpipe(us->pusb_dev, us->send_bulk_ep);
- int dir_in = US_DIRECTION(srb->cmd[0]);
-
- srb->trans_bytes = 0;
+ int dir_in = US_DIRECTION(cmd[0]);
/* set up the command wrapper */
cbw.Signature = cpu_to_le32(US_BULK_CB_SIGN);
- cbw.DataTransferLength = cpu_to_le32(srb->datalen);
+ cbw.DataTransferLength = cpu_to_le32(datalen);
cbw.Flags = (dir_in ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT);
cbw.Tag = ++cbw_tag;
- cbw.Lun = srb->lun;
- cbw.Length = srb->cmdlen;
+ cbw.Lun = usb_blkdev->lun;
+ cbw.Length = cmdlen;
/* copy the command payload */
- memcpy(cbw.CDB, srb->cmd, cbw.Length);
+ memcpy(cbw.CDB, cmd, cbw.Length);
/* send it to out endpoint */
- US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
- le32_to_cpu(cbw.Signature), cbw.Tag,
- le32_to_cpu(cbw.DataTransferLength), cbw.Flags,
- (cbw.Lun >> 4), (cbw.Lun & 0x0F),
- cbw.Length);
+ dev_dbg(dev, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
+ le32_to_cpu(cbw.Signature), cbw.Tag,
+ le32_to_cpu(cbw.DataTransferLength), cbw.Flags,
+ (cbw.Lun >> 4), (cbw.Lun & 0x0F),
+ cbw.Length);
result = usb_bulk_msg(us->pusb_dev, pipeout, &cbw, US_BULK_CB_WRAP_LEN,
&actlen, USB_BULK_TO);
- US_DEBUGP("Bulk command transfer result=%d\n", result);
+ dev_dbg(dev, "Bulk command transfer result=%d\n", result);
if (result < 0) {
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_FAILED;
@@ -136,36 +137,36 @@ int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
mdelay(1);
data_actlen = 0;
- if (srb->datalen) {
+ if (datalen) {
unsigned int pipe = dir_in ? pipein : pipeout;
- result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata,
- srb->datalen, &data_actlen, USB_BULK_TO);
- US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+ result = usb_bulk_msg(us->pusb_dev, pipe, data,
+ datalen, &data_actlen, USB_BULK_TO);
+ dev_dbg(dev, "Bulk data transfer result 0x%x\n", result);
/* special handling of STALL in DATA phase */
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
- US_DEBUGP("DATA: stall\n");
+ dev_dbg(dev, "DATA: stall\n");
/* clear the STALL on the endpoint */
result = usb_stor_Bulk_clear_endpt_stall(us, pipe);
}
if (result < 0) {
- US_DEBUGP("Device status: %lx\n", us->pusb_dev->status);
+ dev_dbg(dev, "Device status: %lx\n", us->pusb_dev->status);
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_FAILED;
}
}
/* STATUS phase + error handling */
- US_DEBUGP("Attempting to get CSW...\n");
+ dev_dbg(dev, "Attempting to get CSW...\n");
result = usb_bulk_msg(us->pusb_dev, pipein, &csw, US_BULK_CS_WRAP_LEN,
&actlen, USB_BULK_TO);
/* did the endpoint stall? */
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
- US_DEBUGP("STATUS: stall\n");
+ dev_dbg(dev, "STATUS: stall\n");
/* clear the STALL on the endpoint */
result = usb_stor_Bulk_clear_endpt_stall(us, pipein);
if (result >= 0) {
- US_DEBUGP("Attempting to get CSW...\n");
+ dev_dbg(dev, "Attempting to get CSW...\n");
result = usb_bulk_msg(us->pusb_dev, pipein,
&csw, US_BULK_CS_WRAP_LEN,
&actlen, USB_BULK_TO);
@@ -173,36 +174,35 @@ int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
}
if (result < 0) {
- US_DEBUGP("Device status: %lx\n", us->pusb_dev->status);
+ dev_dbg(dev, "Device status: %lx\n", us->pusb_dev->status);
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_FAILED;
}
/* check bulk status */
residue = le32_to_cpu(csw.Residue);
- US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
- le32_to_cpu(csw.Signature), csw.Tag, residue, csw.Status);
+ dev_dbg(dev, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
+ le32_to_cpu(csw.Signature), csw.Tag, residue, csw.Status);
if (csw.Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
- US_DEBUGP("Bad CSW signature\n");
+ dev_dbg(dev, "Bad CSW signature\n");
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw.Tag != cbw_tag) {
- US_DEBUGP("Mismatching tag\n");
+ dev_dbg(dev, "Mismatching tag\n");
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw.Status >= US_BULK_STAT_PHASE) {
- US_DEBUGP("Status >= phase\n");
+ dev_dbg(dev, "Status >= phase\n");
usb_stor_Bulk_reset(us);
return USB_STOR_TRANSPORT_ERROR;
- } else if (residue > srb->datalen) {
- US_DEBUGP("residue (%uB) > req data (%luB)\n",
- residue, srb->datalen);
+ } else if (residue > datalen) {
+ dev_dbg(dev, "residue (%uB) > req data (%uB)\n",
+ residue, datalen);
return USB_STOR_TRANSPORT_FAILED;
} else if (csw.Status == US_BULK_STAT_FAIL) {
- US_DEBUGP("FAILED\n");
+ dev_dbg(dev, "FAILED\n");
return USB_STOR_TRANSPORT_FAILED;
}
- srb->trans_bytes = min(srb->datalen - residue, (ulong)data_actlen);
return 0;
}
@@ -213,11 +213,12 @@ int usb_stor_Bulk_transport(ccb *srb, struct us_data *us)
*/
int usb_stor_Bulk_reset(struct us_data *us)
{
+ struct device_d *dev = &us->pusb_dev->dev;
int result;
int result2;
unsigned int pipe;
- US_DEBUGP("%s called\n", __func__);
+ dev_dbg(dev, "%s called\n", __func__);
/* issue the command */
result = usb_control_msg(us->pusb_dev,
@@ -226,24 +227,24 @@ int usb_stor_Bulk_reset(struct us_data *us)
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT);
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
- US_DEBUGP("Soft reset stalled: %d\n", result);
+ dev_dbg(dev, "Soft reset stalled: %d\n", result);
return result;
}
mdelay(150);
/* clear the bulk endpoints halt */
- US_DEBUGP("Soft reset: clearing %s endpoint halt\n", "bulk-in");
+ dev_dbg(dev, "Soft reset: clearing %s endpoint halt\n", "bulk-in");
pipe = usb_rcvbulkpipe(us->pusb_dev, us->recv_bulk_ep);
result = usb_clear_halt(us->pusb_dev, pipe);
mdelay(150);
- US_DEBUGP("Soft reset: clearing %s endpoint halt\n", "bulk-out");
+ dev_dbg(dev, "Soft reset: clearing %s endpoint halt\n", "bulk-out");
pipe = usb_sndbulkpipe(us->pusb_dev, us->send_bulk_ep);
result2 = usb_clear_halt(us->pusb_dev, pipe);
mdelay(150);
if (result >= 0)
result = result2;
- US_DEBUGP("Soft reset %s\n", ((result < 0) ? "failed" : "done"));
+ dev_dbg(dev, "Soft reset %s\n", ((result < 0) ? "failed" : "done"));
return result;
}
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index bc8a7693f8..22d7dea3f5 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -84,7 +84,7 @@ struct bulk_cs_wrap {
struct us_data;
-extern int usb_stor_Bulk_transport(ccb *, struct us_data *);
+extern trans_cmnd usb_stor_Bulk_transport;
extern int usb_stor_Bulk_max_lun(struct us_data *);
extern int usb_stor_Bulk_reset(struct us_data *);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 8218bb2a71..fda24d6167 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -26,164 +26,176 @@
#include <usb/usb.h>
#include <usb/usb_defs.h>
-#undef USB_STOR_DEBUG
+#include <asm/unaligned.h>
#include "usb.h"
#include "transport.h"
-static LIST_HEAD(us_blkdev_list);
-
-
/***********************************************************************
* USB Storage routines
***********************************************************************/
-static int usb_stor_inquiry(ccb *srb, struct us_data *us)
+#define USB_STOR_NO_REQUEST_SENSE -1
+
+static int usb_stor_request_sense(struct us_blk_dev *usb_blkdev)
{
- int retries, result;
+ struct us_data *us = usb_blkdev->us;
+ struct device_d *dev = &us->pusb_dev->dev;
+ u8 cmd[6];
+ const u8 datalen = 18;
+ u8 *data = xzalloc(datalen);
- srb->datalen = min(128UL, srb->datalen);
- if (srb->datalen < 5) {
- US_DEBUGP("SCSI_INQUIRY: invalid data buffer size\n");
- return -EINVAL;
- }
+ dev_dbg(dev, "SCSI_REQ_SENSE\n");
- retries = 3;
- do {
- US_DEBUGP("SCSI_INQUIRY\n");
- memset(&srb->cmd[0], 0, 6);
- srb->cmdlen = 6;
- srb->cmd[0] = SCSI_INQUIRY;
- srb->cmd[3] = (u8)(srb->datalen >> 8);
- srb->cmd[4] = (u8)(srb->datalen >> 0);
- result = us->transport(srb, us);
- US_DEBUGP("SCSI_INQUIRY returns %d\n", result);
- } while ((result != USB_STOR_TRANSPORT_GOOD) && retries--);
-
- return (result != USB_STOR_TRANSPORT_GOOD) ? -EIO : 0;
-}
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = SCSI_REQ_SENSE;
+ cmd[4] = datalen;
+ us->transport(usb_blkdev, cmd, sizeof(cmd), data, datalen);
+ dev_dbg(dev, "Request Sense returned %02X %02X %02X\n",
+ data[2], data[12], data[13]);
-static int usb_stor_request_sense(ccb *srb, struct us_data *us)
-{
- unsigned char *pdata = srb->pdata;
- unsigned long datalen = srb->datalen;
-
- US_DEBUGP("SCSI_REQ_SENSE\n");
- srb->pdata = &srb->sense_buf[0];
- srb->datalen = 18;
- memset(&srb->cmd[0], 0, 6);
- srb->cmdlen = 6;
- srb->cmd[0] = SCSI_REQ_SENSE;
- srb->cmd[4] = (u8)(srb->datalen >> 0);
- us->transport(srb, us);
- US_DEBUGP("Request Sense returned %02X %02X %02X\n",
- srb->sense_buf[2], srb->sense_buf[12], srb->sense_buf[13]);
- srb->pdata = pdata;
- srb->datalen = datalen;
+ free(data);
return 0;
}
-static int usb_stor_test_unit_ready(ccb *srb, struct us_data *us)
+static const char *usb_stor_opcode_name(u8 opcode)
{
- int retries, result;
-
- retries = 10;
- do {
- US_DEBUGP("SCSI_TST_U_RDY\n");
- memset(&srb->cmd[0], 0, 12);
- srb->cmdlen = 12;
- srb->cmd[0] = SCSI_TST_U_RDY;
- srb->datalen = 0;
- result = us->transport(srb, us);
- US_DEBUGP("SCSI_TST_U_RDY returns %d\n", result);
- if (result == USB_STOR_TRANSPORT_GOOD)
- return 0;
- usb_stor_request_sense(srb, us);
- mdelay(100);
- } while (retries--);
-
- return -1;
+ switch (opcode) {
+ case SCSI_INQUIRY:
+ return "SCSI_INQUIRY";
+ case SCSI_TST_U_RDY:
+ return "SCSI_TST_U_RDY";
+ case SCSI_RD_CAPAC:
+ return "SCSI_RD_CAPAC";
+ case SCSI_READ10:
+ return "SCSI_READ10";
+ case SCSI_WRITE10:
+ return "SCSI_WRITE10";
+ };
+
+ return "UNKNOWN";
}
-static int usb_stor_read_capacity(ccb *srb, struct us_data *us)
+static int usb_stor_transport(struct us_blk_dev *usb_blkdev,
+ const u8 *cmd, u8 cmdlen,
+ void *data, u32 datalen,
+ int retries, int request_sense_delay_ms)
{
- int retries, result;
+ struct us_data *us = usb_blkdev->us;
+ struct device_d *dev = &us->pusb_dev->dev;
+ int i, ret;
+
- if (srb->datalen < 8) {
- US_DEBUGP("SCSI_RD_CAPAC: invalid data buffer size\n");
- return -EINVAL;
+ for (i = 0; i < retries; i++) {
+ dev_dbg(dev, "%s\n", usb_stor_opcode_name(cmd[0]));
+ ret = us->transport(usb_blkdev, cmd, cmdlen, data, datalen);
+ dev_dbg(dev, "%s returns %d\n", usb_stor_opcode_name(cmd[0]),
+ ret);
+ if (ret == USB_STOR_TRANSPORT_GOOD)
+ return 0;
+
+ if (request_sense_delay_ms == USB_STOR_NO_REQUEST_SENSE)
+ continue;
+
+ usb_stor_request_sense(usb_blkdev);
+
+ if (request_sense_delay_ms)
+ mdelay(request_sense_delay_ms);
}
- retries = 3;
- do {
- US_DEBUGP("SCSI_RD_CAPAC\n");
- memset(&srb->cmd[0], 0, 10);
- srb->cmdlen = 10;
- srb->cmd[0] = SCSI_RD_CAPAC;
- srb->datalen = 8;
- result = us->transport(srb, us);
- US_DEBUGP("SCSI_RD_CAPAC returns %d\n", result);
- } while ((result != USB_STOR_TRANSPORT_GOOD) && retries--);
-
- return (result != USB_STOR_TRANSPORT_GOOD) ? -EIO : 0;
+ return -EIO;
}
-static int usb_stor_read_10(ccb *srb, struct us_data *us,
- unsigned long start, unsigned short blocks)
+static int usb_stor_inquiry(struct us_blk_dev *usb_blkdev)
{
- int retries, result;
-
- retries = 2;
- do {
- US_DEBUGP("SCSI_READ10: start %lx blocks %x\n", start, blocks);
- memset(&srb->cmd[0], 0, 10);
- srb->cmdlen = 10;
- srb->cmd[0] = SCSI_READ10;
- srb->cmd[2] = (u8)(start >> 24);
- srb->cmd[3] = (u8)(start >> 16);
- srb->cmd[4] = (u8)(start >> 8);
- srb->cmd[5] = (u8)(start >> 0);
- srb->cmd[7] = (u8)(blocks >> 8);
- srb->cmd[8] = (u8)(blocks >> 0);
- result = us->transport(srb, us);
- US_DEBUGP("SCSI_READ10 returns %d\n", result);
- if (result == USB_STOR_TRANSPORT_GOOD)
- return 0;
- usb_stor_request_sense(srb, us);
- } while (retries--);
+ struct device_d *dev = &usb_blkdev->us->pusb_dev->dev;
+ int ret;
+ u8 cmd[6];
+ const u16 datalen = 36;
+ u8 *data = xzalloc(datalen);
+
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = SCSI_INQUIRY;
+ put_unaligned_be16(datalen, &cmd[3]);
+
+ ret = usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), data, datalen,
+ 3, USB_STOR_NO_REQUEST_SENSE);
+ if (ret < 0) {
+ ret = -ENODEV;
+ goto exit;
+ }
- return -EIO;
+ dev_dbg(dev, "Peripheral type: %x, removable: %x\n",
+ data[0], (data[1] >> 7));
+ dev_dbg(dev, "ISO ver: %x, resp format: %x\n",
+ data[2], data[3]);
+ dev_dbg(dev, "Vendor/product/rev: %28s\n",
+ &data[8]);
+ // TODO: process and store device info
+
+exit:
+ free(data);
+ return ret;
}
-static int usb_stor_write_10(ccb *srb, struct us_data *us,
- unsigned long start, unsigned short blocks)
+static int usb_stor_test_unit_ready(struct us_blk_dev *usb_blkdev)
{
- int retries, result;
-
- retries = 2;
- do {
- US_DEBUGP("SCSI_WRITE10: start %lx blocks %x\n", start, blocks);
- memset(&srb->cmd[0], 0, 10);
- srb->cmdlen = 10;
- srb->cmd[0] = SCSI_WRITE10;
- srb->cmd[2] = (u8)(start >> 24);
- srb->cmd[3] = (u8)(start >> 16);
- srb->cmd[4] = (u8)(start >> 8);
- srb->cmd[5] = (u8)(start >> 0);
- srb->cmd[7] = (u8)(blocks >> 8);
- srb->cmd[8] = (u8)(blocks >> 0);
- result = us->transport(srb, us);
- US_DEBUGP("SCSI_WRITE10 returns %d\n", result);
- if (result == USB_STOR_TRANSPORT_GOOD)
- return 0;
- usb_stor_request_sense(srb, us);
- } while (retries--);
+ u8 cmd[12];
+ int ret;
+
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = SCSI_TST_U_RDY;
- return us->transport(srb, us);
+ ret = usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), NULL, 0,
+ 10, 100);
+ if (ret < 0)
+ return -ENODEV;
+
+ return 0;
}
+static int usb_stor_read_capacity(struct us_blk_dev *usb_blkdev,
+ u32 *last_lba, u32 *block_length)
+{
+ struct device_d *dev = &usb_blkdev->us->pusb_dev->dev;
+ const u32 datalen = 8;
+ u32 *data = xzalloc(datalen);
+ u8 cmd[10];
+ int ret;
+
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = SCSI_RD_CAPAC;
+
+ ret = usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), data, datalen,
+ 3, USB_STOR_NO_REQUEST_SENSE);
+ if (ret < 0)
+ goto exit;
+
+ dev_dbg(dev, "Read Capacity returns: 0x%x, 0x%x\n",
+ data[0], data[1]);
+ *last_lba = be32_to_cpu(data[0]);
+ *block_length = be32_to_cpu(data[1]);
+
+exit:
+ free(data);
+ return ret;
+}
+
+static int usb_stor_io_10(struct us_blk_dev *usb_blkdev, u8 opcode,
+ u32 start, u8 *data, u16 blocks)
+{
+ u8 cmd[10];
+
+ memset(cmd, 0, sizeof(cmd));
+ cmd[0] = opcode;
+ put_unaligned_be32(start, &cmd[2]);
+ put_unaligned_be16(blocks, &cmd[7]);
+
+ return usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), data,
+ blocks * SECTOR_SIZE, 2, 0);
+}
/***********************************************************************
* Disk driver interface
@@ -191,101 +203,59 @@ static int usb_stor_write_10(ccb *srb, struct us_data *us,
#define US_MAX_IO_BLK 32
-#define to_usb_mass_storage(x) container_of((x), struct us_blk_dev, blk)
-
-enum { io_rd, io_wr };
-
/* Read / write a chunk of sectors on media */
-static int usb_stor_blk_io(int io_op, struct block_device *disk_dev,
- int sector_start, int sector_count, void *buffer)
+static int usb_stor_blk_io(struct block_device *disk_dev,
+ int sector_start, int sector_count, void *buffer,
+ bool read)
{
- struct us_blk_dev *pblk_dev = to_usb_mass_storage(disk_dev);
+ struct us_blk_dev *pblk_dev = container_of(disk_dev,
+ struct us_blk_dev,
+ blk);
struct us_data *us = pblk_dev->us;
- ccb us_ccb;
- unsigned sectors_done;
-
- if (sector_count == 0)
- return 0;
-
- /* check for unsupported block size */
- if (pblk_dev->blk.blockbits != SECTOR_SHIFT) {
- US_DEBUGP("%s: unsupported block shift %d\n",
- __func__, pblk_dev->blk.blockbits);
- return -EINVAL;
- }
-
- /* check for invalid sector_start */
- if (sector_start >= pblk_dev->blk.num_blocks || sector_start > (ulong)-1) {
- US_DEBUGP("%s: start sector %d too large\n",
- __func__, sector_start);
- return -EINVAL;
- }
-
- us_ccb.lun = pblk_dev->lun;
- usb_disable_asynch(1);
+ struct device_d *dev = &us->pusb_dev->dev;
/* ensure unit ready */
- US_DEBUGP("Testing for unit ready\n");
- if (usb_stor_test_unit_ready(&us_ccb, us)) {
- US_DEBUGP("Device NOT ready\n");
- usb_disable_asynch(0);
+ dev_dbg(dev, "Testing for unit ready\n");
+ if (usb_stor_test_unit_ready(pblk_dev)) {
+ dev_dbg(dev, "Device NOT ready\n");
return -EIO;
}
- /* possibly limit the amount of I/O data */
- if (sector_count > INT_MAX) {
- sector_count = INT_MAX;
- US_DEBUGP("Restricting I/O to %u blocks\n", sector_count);
- }
- if (sector_start + sector_count > pblk_dev->blk.num_blocks) {
- sector_count = pblk_dev->blk.num_blocks - sector_start;
- US_DEBUGP("Restricting I/O to %u blocks\n", sector_count);
- }
-
/* read / write the requested data */
- US_DEBUGP("%s %u block(s), starting from %d\n",
- ((io_op == io_rd) ? "Read" : "Write"),
- sector_count, sector_start);
- sectors_done = 0;
+ dev_dbg(dev, "%s %u block(s), starting from %d\n",
+ read ? "Read" : "Write",
+ sector_count, sector_start);
+
while (sector_count > 0) {
- int result;
unsigned n = min(sector_count, US_MAX_IO_BLK);
- us_ccb.pdata = buffer + (sectors_done * SECTOR_SIZE);
- us_ccb.datalen = n * SECTOR_SIZE;
- if (io_op == io_rd)
- result = usb_stor_read_10(&us_ccb, us,
- (ulong)sector_start, n);
- else
- result = usb_stor_write_10(&us_ccb, us,
- (ulong)sector_start, n);
- if (result != 0) {
- US_DEBUGP("I/O error at sector %d\n", sector_start);
+
+ if (usb_stor_io_10(pblk_dev,
+ read ? SCSI_READ10 : SCSI_WRITE10,
+ sector_start,
+ buffer, n)) {
+ dev_dbg(dev, "I/O error at sector %d\n", sector_start);
break;
}
sector_start += n;
sector_count -= n;
- sectors_done += n;
+ buffer += n * SECTOR_SIZE;
}
- usb_disable_asynch(0);
-
- US_DEBUGP("Successful I/O of %d blocks\n", sectors_done);
-
- return (sector_count != 0) ? -EIO : 0;
+ return sector_count ? -EIO : 0;
}
/* Write a chunk of sectors to media */
static int __maybe_unused usb_stor_blk_write(struct block_device *blk,
const void *buffer, int block, int num_blocks)
{
- return usb_stor_blk_io(io_wr, blk, block, num_blocks, (void *)buffer);
+ return usb_stor_blk_io(blk, block, num_blocks, (void *)buffer, false);
}
/* Read a chunk of sectors from media */
static int usb_stor_blk_read(struct block_device *blk, void *buffer, int block,
int num_blocks)
{
- return usb_stor_blk_io(io_rd, blk, block, num_blocks, buffer);
+ return usb_stor_blk_io(blk, block, num_blocks, buffer, true);
}
static struct block_device_ops usb_mass_storage_ops = {
@@ -299,82 +269,61 @@ static struct block_device_ops usb_mass_storage_ops = {
* Block device routines
***********************************************************************/
-static unsigned char us_io_buf[512];
-
-static int usb_limit_blk_cnt(unsigned cnt)
-{
- if (cnt > 0x7fffffff) {
- pr_warn("Limiting device size due to 31 bit contraints\n");
- return 0x7fffffff;
- }
-
- return (int)cnt;
-}
-
/* Prepare a disk device */
static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev)
{
struct us_data *us = pblk_dev->us;
- ccb us_ccb;
- unsigned long *pcap;
- int result = 0;
-
- us_ccb.pdata = us_io_buf;
- us_ccb.lun = pblk_dev->lun;
-
- pblk_dev->blk.num_blocks = 0;
- usb_disable_asynch(1);
+ struct device_d *dev = &us->pusb_dev->dev;
+ u32 last_lba = 0, block_length = 0;
+ int result;
/* get device info */
- US_DEBUGP("Reading device info\n");
- us_ccb.datalen = 36;
- if (usb_stor_inquiry(&us_ccb, us)) {
- US_DEBUGP("Cannot read device info\n");
- result = -ENODEV;
- goto Exit;
+ dev_dbg(dev, "Reading device info\n");
+
+ result = usb_stor_inquiry(pblk_dev);
+ if (result) {
+ dev_dbg(dev, "Cannot read device info\n");
+ return result;
}
- US_DEBUGP("Peripheral type: %x, removable: %x\n",
- us_io_buf[0], (us_io_buf[1] >> 7));
- US_DEBUGP("ISO ver: %x, resp format: %x\n", us_io_buf[2], us_io_buf[3]);
- US_DEBUGP("Vendor/product/rev: %28s\n", &us_io_buf[8]);
- // TODO: process and store device info
/* ensure unit ready */
- US_DEBUGP("Testing for unit ready\n");
- us_ccb.datalen = 0;
- if (usb_stor_test_unit_ready(&us_ccb, us)) {
- US_DEBUGP("Device NOT ready\n");
- result = -ENODEV;
- goto Exit;
+ dev_dbg(dev, "Testing for unit ready\n");
+
+ result = usb_stor_test_unit_ready(pblk_dev);
+ if (result) {
+ dev_dbg(dev, "Device NOT ready\n");
+ return result;
}
/* read capacity */
- US_DEBUGP("Reading capacity\n");
- memset(us_ccb.pdata, 0, 8);
- us_ccb.datalen = sizeof(us_io_buf);
- if (usb_stor_read_capacity(&us_ccb, us) != 0) {
- US_DEBUGP("Cannot read device capacity\n");
- result = -EIO;
- goto Exit;
+ dev_dbg(dev, "Reading capacity\n");
+
+ result = usb_stor_read_capacity(pblk_dev, &last_lba, &block_length);
+ if (result < 0) {
+ dev_dbg(dev, "Cannot read device capacity\n");
+ return result;
}
- pcap = (unsigned long *)us_ccb.pdata;
- US_DEBUGP("Read Capacity returns: 0x%lx, 0x%lx\n", pcap[0], pcap[1]);
- pblk_dev->blk.num_blocks = usb_limit_blk_cnt(be32_to_cpu(pcap[0]) + 1);
- if (be32_to_cpu(pcap[1]) != SECTOR_SIZE)
+
+ if (last_lba > INT_MAX - 1) {
+ last_lba = INT_MAX - 1;
+ dev_warn(dev,
+ "Limiting device size due to 31 bit contraints\n");
+ }
+
+ pblk_dev->blk.num_blocks = last_lba + 1;
+ if (block_length != SECTOR_SIZE)
pr_warn("Support only %d bytes sectors\n", SECTOR_SIZE);
pblk_dev->blk.blockbits = SECTOR_SHIFT;
- US_DEBUGP("Capacity = 0x%x, blockshift = 0x%x\n",
- pblk_dev->blk.num_blocks, pblk_dev->blk.blockbits);
+ dev_dbg(dev, "Capacity = 0x%x, blockshift = 0x%x\n",
+ pblk_dev->blk.num_blocks, pblk_dev->blk.blockbits);
-Exit:
- usb_disable_asynch(0);
- return result;
+ return 0;
}
/* Create and register a disk device for the specified LUN */
-static int usb_stor_add_blkdev(struct us_data *us, struct device_d *dev,
- unsigned char lun)
+static int usb_stor_add_blkdev(struct us_data *us, unsigned char lun)
{
+ struct device_d *dev = &us->pusb_dev->dev;
struct us_blk_dev *pblk_dev;
int result;
@@ -412,12 +361,12 @@ static int usb_stor_add_blkdev(struct us_data *us, struct device_d *dev,
dev_warn(dev, "No partition table found\n");
list_add_tail(&pblk_dev->list, &us->blk_dev_list);
- US_DEBUGP("USB disk device successfully added\n");
+ dev_dbg(dev, "USB disk device successfully added\n");
return 0;
BadDevice:
- US_DEBUGP("%s failed with %d\n", __func__, result);
+ dev_dbg(dev, "%s failed with %d\n", __func__, result);
free(pblk_dev);
return result;
}
@@ -429,6 +378,7 @@ BadDevice:
/* Get the transport settings */
static void get_transport(struct us_data *us)
{
+ struct device_d *dev = &us->pusb_dev->dev;
switch (us->protocol) {
case US_PR_BULK:
us->transport_name = "Bulk";
@@ -437,17 +387,17 @@ static void get_transport(struct us_data *us)
break;
}
- US_DEBUGP("Transport: %s\n", us->transport_name);
+ dev_dbg(dev, "Transport: %s\n", us->transport_name);
}
/* Get the endpoint settings */
static int get_pipes(struct us_data *us, struct usb_interface *intf)
{
+ struct device_d *dev = &us->pusb_dev->dev;
unsigned int i;
struct usb_endpoint_descriptor *ep;
struct usb_endpoint_descriptor *ep_in = NULL;
struct usb_endpoint_descriptor *ep_out = NULL;
- struct usb_endpoint_descriptor *ep_int = NULL;
/*
* Find the first endpoint of each type we need.
@@ -468,44 +418,38 @@ static int get_pipes(struct us_data *us, struct usb_interface *intf)
ep_out = ep;
}
}
- else if (USB_EP_IS_INT_IN(ep)) {
- if (!ep_int)
- ep_int = ep;
- }
}
- if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
- US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
+ if (!ep_in || !ep_out || us->protocol == US_PR_CBI) {
+ dev_dbg(dev, "Endpoint sanity check failed! Rejecting dev.\n");
return -EIO;
}
/* Store the pipe values */
us->send_bulk_ep = USB_EP_NUM(ep_out);
us->recv_bulk_ep = USB_EP_NUM(ep_in);
- if (ep_int) {
- us->recv_intr_ep = USB_EP_NUM(ep_int);
- us->ep_bInterval = ep_int->bInterval;
- }
+
return 0;
}
/* Scan device's LUNs, registering a disk device for each LUN */
static int usb_stor_scan(struct usb_device *usbdev, struct us_data *us)
{
+ struct device_d *dev = &usbdev->dev;
unsigned char lun;
int num_devs = 0;
/* obtain the max LUN */
- us->max_lun = 0;
+ us->max_lun = 1;
if (us->protocol == US_PR_BULK)
us->max_lun = usb_stor_Bulk_max_lun(us);
/* register a disk device for each active LUN */
for (lun=0; lun<=us->max_lun; lun++) {
- if (usb_stor_add_blkdev(us, &usbdev->dev, lun) == 0)
+ if (usb_stor_add_blkdev(us, lun) == 0)
num_devs++;
}
- US_DEBUGP("Found %d block devices on %s\n", num_devs, usbdev->dev.name);
+ dev_dbg(dev, "Found %d block devices on %s\n", num_devs, usbdev->dev.name);
return num_devs ? 0 : -ENODEV;
}
@@ -514,12 +458,13 @@ static int usb_stor_scan(struct usb_device *usbdev, struct us_data *us)
static int usb_stor_probe(struct usb_device *usbdev,
const struct usb_device_id *id)
{
+ struct device_d *dev = &usbdev->dev;
struct us_data *us;
int result;
int ifno;
struct usb_interface *intf;
- US_DEBUGP("Supported USB Mass Storage device detected\n");
+ dev_dbg(dev, "Supported USB Mass Storage device detected\n");
/* scan usbdev interfaces again to find one that we can handle */
for (ifno=0; ifno<usbdev->config.no_of_if; ifno++) {
@@ -538,19 +483,14 @@ static int usb_stor_probe(struct usb_device *usbdev,
if (result)
return result;
- US_DEBUGP("Selected interface %d\n", (int)intf->desc.bInterfaceNumber);
+ dev_dbg(dev, "Selected interface %d\n", (int)intf->desc.bInterfaceNumber);
/* allocate us_data structure */
- us = (struct us_data *)malloc(sizeof(struct us_data));
- if (!us)
- return -ENOMEM;
- memset(us, 0, sizeof(struct us_data));
+ us = xzalloc(sizeof(*us));
/* initialize the us_data structure */
us->pusb_dev = usbdev;
- us->flags = 0;
us->ifnum = intf->desc.bInterfaceNumber;
- us->subclass = intf->desc.bInterfaceSubClass;
us->protocol = intf->desc.bInterfaceProtocol;
INIT_LIST_HEAD(&us->blk_dev_list);
@@ -571,7 +511,7 @@ static int usb_stor_probe(struct usb_device *usbdev,
return 0;
BadDevice:
- US_DEBUGP("%s failed with %d\n", __func__, result);
+ dev_dbg(dev, "%s failed with %d\n", __func__, result);
free(us);
return result;
}
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index e649d53361..cd4904f03b 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -28,13 +28,6 @@
#include <linux/list.h>
-#ifdef USB_STOR_DEBUG
-#define US_DEBUGP(fmt, args...) printf(fmt , ##args)
-#else
-#define US_DEBUGP(fmt, args...)
-#endif
-
-
/* some defines, similar to ch9.h */
#define USB_EP_NUM(epd) \
((epd)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
@@ -51,32 +44,30 @@
struct us_data;
+struct us_blk_dev;
-typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
+typedef int (trans_cmnd)(struct us_blk_dev *usb_blkdev,
+ const u8 *cmd, u8 cmdlen,
+ void *data, u32 datalen);
typedef int (*trans_reset)(struct us_data *data);
/* one us_data object allocated per usb storage device */
struct us_data {
struct usb_device *pusb_dev; /* this usb_device */
- unsigned int flags; /* from filter */
unsigned char send_bulk_ep; /* used endpoints */
unsigned char recv_bulk_ep;
- unsigned char recv_intr_ep;
unsigned char ifnum; /* interface number */
- unsigned char subclass;
unsigned char protocol;
unsigned char max_lun;
- unsigned char ep_bInterval;
char *transport_name;
- trans_cmnd transport; /* transport function */
+ trans_cmnd *transport; /* transport function */
trans_reset transport_reset;/* transport device reset */
/* SCSI interfaces */
- ccb *srb; /* current srb */
struct list_head blk_dev_list;
};