X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fusb_storage.c;h=097b6729c14d14c1dfd968499e056d8b07b60775;hb=c3bfad825a71eafb16fa9ff95e2ae01c23448a53;hp=df0b057308791f938592c3335d0362e424672d6b;hpb=b9560ad649b8c523bf303cf9ba981e498988c5d9;p=oweals%2Fu-boot.git diff --git a/common/usb_storage.c b/common/usb_storage.c index df0b057308..097b6729c1 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Most of this source has been derived from the Linux USB * project: @@ -17,8 +18,6 @@ * * BBB support based on /sys/dev/usb/umass.c from * FreeBSD. - * - * SPDX-License-Identifier: GPL-2.0+ */ /* Note: @@ -37,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -68,7 +66,7 @@ static __u32 CBWTag; static int usb_max_devs; /* number of highest available usb device */ -#ifndef CONFIG_BLK +#if !CONFIG_IS_ENABLED(BLK) static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV]; #endif @@ -98,20 +96,10 @@ struct us_data { 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_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. - */ -#define USB_MAX_XFER_BLK 65535 -#else -#define USB_MAX_XFER_BLK 20 -#endif - -#ifndef CONFIG_BLK +#if !CONFIG_IS_ENABLED(BLK) static struct us_data usb_stor[USB_MAX_STOR_DEV]; #endif @@ -123,7 +111,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us, struct blk_desc *dev_desc); int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, struct us_data *ss); -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) 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, @@ -148,7 +136,7 @@ static void usb_show_progress(void) int usb_stor_info(void) { int count = 0; -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) struct udevice *dev; for (blk_first_device(IF_TYPE_USB, &dev); @@ -198,7 +186,7 @@ static int usb_stor_probe_device(struct usb_device *udev) { int lun, max_lun; -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) struct us_data *data; int ret; #else @@ -209,7 +197,7 @@ static int usb_stor_probe_device(struct usb_device *udev) #endif debug("\n\nProbing for storage\n"); -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) /* * 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 @@ -238,9 +226,7 @@ static int usb_stor_probe_device(struct usb_device *udev) blkdev->lun = lun; ret = usb_stor_get_info(udev, data, blkdev); - if (ret == 1) - ret = blk_prepare_device(dev); - if (!ret) { + if (ret == 1) { usb_max_devs++; debug("%s: Found device %p\n", __func__, udev); } else { @@ -313,7 +299,7 @@ int usb_stor_scan(int mode) if (mode == 1) printf(" scanning usb for storage devices... "); -#ifndef CONFIG_DM_USB +#if !CONFIG_IS_ENABLED(DM_USB) unsigned char i; usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -664,8 +650,8 @@ static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us) int timeout; us->ip_wanted = 1; - submit_int_msg(us->pusb_dev, us->irqpipe, - (void *) &us->ip_data, us->irqmaxp, us->irqinterval); + usb_int_msg(us->pusb_dev, us->irqpipe, + (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false); timeout = 1000; while (timeout--) { if (us->ip_wanted == 0) @@ -949,6 +935,39 @@ do_retry: return USB_STOR_TRANSPORT_FAILED; } +static void usb_stor_set_max_xfer_blk(struct usb_device *udev, + struct us_data *us) +{ + /* + * Limit the total size of a transfer to 120 KB. + * + * Some devices are known to choke with anything larger. It seems like + * the problem stems from the fact that original IDE controllers had + * only an 8-bit register to hold the number of sectors in one transfer + * and even those couldn't handle a full 256 sectors. + * + * Because we want to make sure we interoperate with as many devices as + * possible, we will maintain a 240 sector transfer size limit for USB + * Mass Storage devices. + * + * Tests show that other operating have similar limits with Microsoft + * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3 + * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2 + * and 2048 for USB3 devices. + */ + unsigned short blk = 240; + +#if CONFIG_IS_ENABLED(DM_USB) + size_t size; + int ret; + + ret = usb_get_max_xfer_size(udev, (size_t *)&size); + if ((ret >= 0) && (size < blk * 512)) + blk = size / 512; +#endif + + us->max_xfer_blk = blk; +} static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss) { @@ -1101,7 +1120,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor, } #endif /* CONFIG_USB_BIN_FIXUP */ -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) #else @@ -1116,14 +1135,14 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, struct us_data *ss; int retry; struct scsi_cmd *srb = &usb_ccb; -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) struct blk_desc *block_dev; #endif if (blkcnt == 0) return 0; /* Setup device */ -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) block_dev = dev_get_uclass_platdata(dev); udev = dev_get_parent_priv(dev_get_parent(dev)); debug("\nusb_read: udev %d\n", block_dev->devnum); @@ -1143,24 +1162,25 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, start = blknr; blks = blkcnt; - debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %" - PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr); + debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + block_dev->devnum, start, blks, buf_addr); do { /* 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; if (usb_read_10(srb, ss, start, smallblks)) { debug("Read ERROR\n"); + ss->flags &= ~USB_READY; usb_request_sense(srb, ss); if (retry--) goto retry_it; @@ -1171,19 +1191,17 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); - ss->flags &= ~USB_READY; - debug("usb_read: end startblk " LBAF - ", blccnt %x buffer %" PRIxPTR "\n", + debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\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; } -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) #else @@ -1198,7 +1216,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, struct us_data *ss; int retry; struct scsi_cmd *srb = &usb_ccb; -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) struct blk_desc *block_dev; #endif @@ -1206,7 +1224,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, return 0; /* Setup device */ -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) block_dev = dev_get_uclass_platdata(dev); udev = dev_get_parent_priv(dev_get_parent(dev)); debug("\nusb_read: udev %d\n", block_dev->devnum); @@ -1227,8 +1245,8 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, start = blknr; blks = blkcnt; - debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %" - PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr); + debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + block_dev->devnum, start, blks, buf_addr); do { /* If write fails retry for max retry count else @@ -1236,17 +1254,18 @@ 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; if (usb_write_10(srb, ss, start, smallblks)) { debug("Write ERROR\n"); + ss->flags &= ~USB_READY; usb_request_sense(srb, ss); if (retry--) goto retry_it; @@ -1257,13 +1276,12 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); - ss->flags &= ~USB_READY; - debug("usb_write: end startblk " LBAF ", blccnt %x buffer %" - PRIxPTR "\n", start, smallblks, buf_addr); + debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\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; @@ -1384,6 +1402,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; } @@ -1448,10 +1470,10 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, memset(pccb->pdata, 0, 8); if (usb_read_capacity(pccb, ss) != 0) { printf("READ_CAP ERROR\n"); + ss->flags &= ~USB_READY; cap[0] = 2880; cap[1] = 0x200; } - ss->flags &= ~USB_READY; debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]); #if 0 if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */ @@ -1474,7 +1496,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, return 1; } -#ifdef CONFIG_DM_USB +#if CONFIG_IS_ENABLED(DM_USB) static int usb_mass_storage_probe(struct udevice *dev) { @@ -1498,7 +1520,7 @@ U_BOOT_DRIVER(usb_mass_storage) = { .id = UCLASS_MASS_STORAGE, .of_match = usb_mass_storage_ids, .probe = usb_mass_storage_probe, -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) .platdata_auto_alloc_size = sizeof(struct us_data), #endif }; @@ -1519,7 +1541,7 @@ static const struct usb_device_id mass_storage_id_table[] = { U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table); #endif -#ifdef CONFIG_BLK +#if CONFIG_IS_ENABLED(BLK) static const struct blk_ops usb_storage_ops = { .read = usb_stor_read, .write = usb_stor_write,