]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - common/usb_storage.c
ARM: dts: DRA7: use new dra7-specific compatible string
[people/ms/u-boot.git] / common / usb_storage.c
index 7e6e52d2ec37a2383935721332a31e2636317e98..a91b1c0d2f925eed06881d14ab85afe398eac423 100644 (file)
@@ -63,7 +63,7 @@ static const unsigned char us_direction[256/8] = {
 };
 #define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
 
-static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
+static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
 static __u32 CBWTag;
 
 static int usb_max_devs; /* number of highest available usb device */
@@ -73,7 +73,7 @@ static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
 #endif
 
 struct us_data;
-typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
+typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
 typedef int (*trans_reset)(struct us_data *data);
 
 struct us_data {
@@ -95,22 +95,12 @@ struct us_data {
        unsigned int    irqpipe;                /* pipe for release_irq */
        unsigned char   irqmaxp;                /* max packed for irq Pipe */
        unsigned char   irqinterval;            /* Intervall for IRQ Pipe */
-       ccb             *srb;                   /* current srb */
+       struct scsi_cmd *srb;                   /* current srb */
        trans_reset     transport_reset;        /* reset routine */
        trans_cmnd      transport;              /* transport routine */
+       unsigned short  max_xfer_blk;           /* maximum transfer blocks */
 };
 
-#ifdef CONFIG_USB_EHCI
-/*
- * 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.
- */
-#define USB_MAX_XFER_BLK       65535
-#else
-#define USB_MAX_XFER_BLK       20
-#endif
-
 #ifndef CONFIG_BLK
 static struct us_data usb_stor[USB_MAX_STOR_DEV];
 #endif
@@ -303,7 +293,6 @@ 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
@@ -311,11 +300,12 @@ void usb_stor_reset(void)
  */
 int usb_stor_scan(int mode)
 {
-       unsigned char i;
-
        if (mode == 1)
                printf("       scanning usb for storage devices... ");
 
+#ifndef CONFIG_DM_USB
+       unsigned char i;
+
        usb_disable_asynch(1); /* asynch transfer not allowed */
 
        usb_stor_reset();
@@ -329,12 +319,12 @@ int usb_stor_scan(int mode)
        } /* for */
 
        usb_disable_asynch(0); /* asynch transfer allowed */
+#endif
        printf("%d Storage Device(s) found\n", usb_max_devs);
        if (usb_max_devs > 0)
                return 0;
        return -1;
 }
-#endif
 
 static int usb_stor_irq(struct usb_device *dev)
 {
@@ -349,7 +339,7 @@ static int usb_stor_irq(struct usb_device *dev)
 
 #ifdef DEBUG
 
-static void usb_show_srb(ccb *pccb)
+static void usb_show_srb(struct scsi_cmd *pccb)
 {
        int i;
        printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
@@ -541,7 +531,7 @@ static int usb_stor_CB_reset(struct us_data *us)
  * Set up the command for a BBB device. Note that the actual SCSI
  * command is copied into cbw.CBWCDB.
  */
-static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
+static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
 {
        int result;
        int actlen;
@@ -590,7 +580,7 @@ static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
 /* FIXME: we also need a CBI_command which sets up the completion
  * interrupt, and waits for it
  */
-static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
+static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
 {
        int result = 0;
        int dir_in, retry;
@@ -659,7 +649,7 @@ static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
 }
 
 
-static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
+static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
 {
        int timeout;
 
@@ -708,16 +698,13 @@ static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
 /* clear a stall on an endpoint - special for BBB devices */
 static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
 {
-       int result;
-
        /* ENDPOINT_HALT = 0, so set value to 0 */
-       result = 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);
-       return result;
+       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);
 }
 
-static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
+static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
 {
        int result, retry;
        int dir_in;
@@ -840,11 +827,11 @@ again:
        return result;
 }
 
-static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
+static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
 {
        int result, status;
-       ccb *psrb;
-       ccb reqsrb;
+       struct scsi_cmd *psrb;
+       struct scsi_cmd reqsrb;
        int retry, notready;
 
        psrb = &reqsrb;
@@ -952,8 +939,40 @@ do_retry:
        return USB_STOR_TRANSPORT_FAILED;
 }
 
+static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
+                                     struct us_data *us)
+{
+       unsigned short blk;
+       size_t __maybe_unused size;
+       int __maybe_unused ret;
+
+#ifndef CONFIG_DM_USB
+#ifdef CONFIG_USB_EHCI_HCD
+       /*
+        * The U-Boot EHCI driver can handle any transfer length as long as
+        * there is enough free heap space left, but the SCSI READ(10) and
+        * WRITE(10) commands are limited to 65535 blocks.
+        */
+       blk = USHRT_MAX;
+#else
+       blk = 20;
+#endif
+#else
+       ret = usb_get_max_xfer_size(udev, (size_t *)&size);
+       if (ret < 0) {
+               /* unimplemented, let's use default 20 */
+               blk = 20;
+       } else {
+               if (size > USHRT_MAX * 512)
+                       size = USHRT_MAX * 512;
+               blk = size / 512;
+       }
+#endif
+
+       us->max_xfer_blk = blk;
+}
 
-static int usb_inquiry(ccb *srb, struct us_data *ss)
+static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retry, i;
        retry = 5;
@@ -977,7 +996,7 @@ static int usb_inquiry(ccb *srb, struct us_data *ss)
        return 0;
 }
 
-static int usb_request_sense(ccb *srb, struct us_data *ss)
+static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
 {
        char *ptr;
 
@@ -997,7 +1016,7 @@ static int usb_request_sense(ccb *srb, struct us_data *ss)
        return 0;
 }
 
-static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
+static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retries = 10;
 
@@ -1028,7 +1047,7 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
        return -1;
 }
 
-static int usb_read_capacity(ccb *srb, struct us_data *ss)
+static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retry;
        /* XXX retries */
@@ -1046,8 +1065,8 @@ static int usb_read_capacity(ccb *srb, struct us_data *ss)
        return -1;
 }
 
-static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
-                      unsigned short blocks)
+static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
+                      unsigned long start, unsigned short blocks)
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_READ10;
@@ -1063,8 +1082,8 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
        return ss->transport(srb, ss);
 }
 
-static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
-                       unsigned short blocks)
+static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
+                       unsigned long start, unsigned short blocks)
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_WRITE10;
@@ -1118,7 +1137,7 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
        struct usb_device *udev;
        struct us_data *ss;
        int retry;
-       ccb *srb = &usb_ccb;
+       struct scsi_cmd *srb = &usb_ccb;
 #ifdef CONFIG_BLK
        struct blk_desc *block_dev;
 #endif
@@ -1153,12 +1172,12 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
                /* XXX need some comment here */
                retry = 2;
                srb->pdata = (unsigned char *)buf_addr;
-               if (blks > USB_MAX_XFER_BLK)
-                       smallblks = USB_MAX_XFER_BLK;
+               if (blks > ss->max_xfer_blk)
+                       smallblks = ss->max_xfer_blk;
                else
                        smallblks = (unsigned short) blks;
 retry_it:
-               if (smallblks == USB_MAX_XFER_BLK)
+               if (smallblks == ss->max_xfer_blk)
                        usb_show_progress();
                srb->datalen = block_dev->blksz * smallblks;
                srb->pdata = (unsigned char *)buf_addr;
@@ -1181,7 +1200,7 @@ retry_it:
              start, smallblks, buf_addr);
 
        usb_disable_asynch(0); /* asynch transfer allowed */
-       if (blkcnt >= USB_MAX_XFER_BLK)
+       if (blkcnt >= ss->max_xfer_blk)
                debug("\n");
        return blkcnt;
 }
@@ -1200,7 +1219,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
        struct usb_device *udev;
        struct us_data *ss;
        int retry;
-       ccb *srb = &usb_ccb;
+       struct scsi_cmd *srb = &usb_ccb;
 #ifdef CONFIG_BLK
        struct blk_desc *block_dev;
 #endif
@@ -1239,12 +1258,12 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
                 */
                retry = 2;
                srb->pdata = (unsigned char *)buf_addr;
-               if (blks > USB_MAX_XFER_BLK)
-                       smallblks = USB_MAX_XFER_BLK;
+               if (blks > ss->max_xfer_blk)
+                       smallblks = ss->max_xfer_blk;
                else
                        smallblks = (unsigned short) blks;
 retry_it:
-               if (smallblks == USB_MAX_XFER_BLK)
+               if (smallblks == ss->max_xfer_blk)
                        usb_show_progress();
                srb->datalen = block_dev->blksz * smallblks;
                srb->pdata = (unsigned char *)buf_addr;
@@ -1266,7 +1285,7 @@ retry_it:
              PRIxPTR "\n", start, smallblks, buf_addr);
 
        usb_disable_asynch(0); /* asynch transfer allowed */
-       if (blkcnt >= USB_MAX_XFER_BLK)
+       if (blkcnt >= ss->max_xfer_blk)
                debug("\n");
        return blkcnt;
 
@@ -1387,6 +1406,10 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
                ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
                dev->irq_handle = usb_stor_irq;
        }
+
+       /* Set the maximum transfer size per host controller setting */
+       usb_stor_set_max_xfer_blk(dev, ss);
+
        dev->privptr = (void *)ss;
        return 1;
 }
@@ -1398,7 +1421,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
        ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
        ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
        u32 capacity, blksz;
-       ccb *pccb = &usb_ccb;
+       struct scsi_cmd *pccb = &usb_ccb;
 
        pccb->pdata = usb_stor_buf;
 
@@ -1443,10 +1466,8 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
                       "   Request Sense returned %02X %02X %02X\n",
                       pccb->sense_buf[2], pccb->sense_buf[12],
                       pccb->sense_buf[13]);
-               if (dev_desc->removable == 1) {
+               if (dev_desc->removable == 1)
                        dev_desc->type = perq;
-                       return 1;
-               }
                return 0;
        }
        pccb->pdata = (unsigned char *)cap;