#include <asm/byteorder.h>
#include <asm/processor.h>
#include <dm/device-internal.h>
+#include <dm/lists.h>
#include <part.h>
#include <usb.h>
static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
static __u32 CBWTag;
-#define USB_MAX_STOR_DEV 5
static int usb_max_devs; /* number of highest available usb device */
-static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
+#ifndef CONFIG_BLK
+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);
#define USB_MAX_XFER_BLK 20
#endif
+#ifndef CONFIG_BLK
static struct us_data usb_stor[USB_MAX_STOR_DEV];
+#endif
#define USB_STOR_TRANSPORT_GOOD 0
#define USB_STOR_TRANSPORT_FAILED -1
#define USB_STOR_TRANSPORT_ERROR -2
int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
- block_dev_desc_t *dev_desc);
+ struct blk_desc *dev_desc);
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
struct us_data *ss);
-unsigned long usb_stor_read(int device, lbaint_t blknr,
- lbaint_t blkcnt, void *buffer);
-unsigned long usb_stor_write(int device, lbaint_t blknr,
- lbaint_t blkcnt, const void *buffer);
-void uhci_show_temp_int_td(void);
-
-#ifdef CONFIG_PARTITIONS
-block_dev_desc_t *usb_stor_get_dev(int index)
-{
- return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL;
-}
+#ifdef CONFIG_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,
+ lbaint_t blkcnt, const void *buffer);
+#else
+static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer);
+static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer);
#endif
+void uhci_show_temp_int_td(void);
static void usb_show_progress(void)
{
*/
int usb_stor_info(void)
{
+ int count = 0;
+#ifdef CONFIG_BLK
+ 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
int i;
if (usb_max_devs > 0) {
}
return 0;
}
+#endif
+ if (!count) {
+ printf("No storage devices, perhaps not 'usb start'ed..?\n");
+ return 1;
+ }
- printf("No storage devices, perhaps not 'usb start'ed..?\n");
- return 1;
+ return 0;
}
static unsigned int usb_get_max_lun(struct us_data *us)
return (len > 0) ? *result : 0;
}
-static int usb_stor_probe_device(struct usb_device *dev)
+static int usb_stor_probe_device(struct usb_device *udev)
{
- if (dev == NULL)
+ int lun, max_lun;
+
+#ifdef CONFIG_BLK
+ struct us_data *data;
+ int ret;
+#else
+ int start;
+
+ if (udev == NULL)
return -ENOENT; /* no more devices available */
+#endif
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);
- }
+#ifdef CONFIG_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
+ * 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;
+ char str[10];
+
+ 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);
+ if (ret) {
+ debug("Cannot bind driver\n");
+ return ret;
}
- }
- /* if storage device */
+ blkdev = dev_get_uclass_platdata(dev);
+ blkdev->target = 0xff;
+ blkdev->lun = lun;
+
+ ret = usb_stor_get_info(udev, data, blkdev);
+ if (ret == 1)
+ ret = blk_prepare_device(dev);
+ if (!ret) {
+ usb_max_devs++;
+ debug("%s: Found device %p\n", __func__, udev);
+ } else {
+ debug("usb_stor_get_info: Invalid device\n");
+ ret = device_unbind(dev);
+ if (ret)
+ return ret;
+ }
+ }
+#else
+ /* 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\n",
usb_max_devs);
return -ENOSPC;
}
+ 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) {
+ debug("partype: %d\n", blkdev->part_type);
+ part_init(blkdev);
+ debug("partype: %d\n", blkdev->part_type);
+ usb_max_devs++;
+ debug("%s: Found device %p\n", __func__, udev);
+ }
+ }
+#endif
+
return 0;
}
us->ip_wanted = 0;
return USB_STOR_TRANSPORT_ERROR;
}
- debug("Got interrupt data 0x%x, transfered %d status 0x%lX\n",
+ debug("Got interrupt data 0x%x, transferred %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 */
* device with proper values (as reported by 'usb info').
*
* Vendor and product length limits are taken from the definition of
- * block_dev_desc_t in include/part.h.
+ * struct blk_desc in include/part.h.
*/
static void usb_bin_fixup(struct usb_device_descriptor descriptor,
unsigned char vendor[],
}
#endif /* CONFIG_USB_BIN_FIXUP */
-unsigned long usb_stor_read(int device, lbaint_t blknr,
- lbaint_t blkcnt, void *buffer)
+#ifdef CONFIG_BLK
+static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer)
+#else
+static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer)
+#endif
{
lbaint_t start, blks;
uintptr_t buf_addr;
unsigned short smallblks;
- struct usb_device *dev;
+ struct usb_device *udev;
struct us_data *ss;
int retry;
ccb *srb = &usb_ccb;
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev;
+#endif
if (blkcnt == 0)
return 0;
-
- device &= 0xff;
/* Setup device */
- debug("\nusb_read: dev %d\n", device);
- dev = usb_dev_desc[device].priv;
- if (!dev) {
+#ifdef CONFIG_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);
+#else
+ debug("\nusb_read: udev %d\n", block_dev->devnum);
+ udev = usb_dev_desc[block_dev->devnum].priv;
+ if (!udev) {
debug("%s: No device\n", __func__);
return 0;
}
- ss = (struct us_data *)dev->privptr;
+#endif
+ ss = (struct us_data *)udev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
- srb->lun = usb_dev_desc[device].lun;
+ srb->lun = block_dev->lun;
buf_addr = (uintptr_t)buffer;
start = blknr;
blks = blkcnt;
- debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF
- " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
+ debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
+ PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
do {
/* XXX need some comment here */
retry_it:
if (smallblks == USB_MAX_XFER_BLK)
usb_show_progress();
- srb->datalen = usb_dev_desc[device].blksz * smallblks;
+ srb->datalen = block_dev->blksz * smallblks;
srb->pdata = (unsigned char *)buf_addr;
if (usb_read_10(srb, ss, start, smallblks)) {
debug("Read ERROR\n");
return blkcnt;
}
-unsigned long usb_stor_write(int device, lbaint_t blknr,
- lbaint_t blkcnt, const void *buffer)
+#ifdef CONFIG_BLK
+static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+#else
+static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+#endif
{
lbaint_t start, blks;
uintptr_t buf_addr;
unsigned short smallblks;
- struct usb_device *dev;
+ struct usb_device *udev;
struct us_data *ss;
int retry;
ccb *srb = &usb_ccb;
+#ifdef CONFIG_BLK
+ struct blk_desc *block_dev;
+#endif
if (blkcnt == 0)
return 0;
- device &= 0xff;
/* Setup device */
- debug("\nusb_write: dev %d\n", device);
- dev = usb_dev_desc[device].priv;
- if (!dev)
+#ifdef CONFIG_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);
+#else
+ debug("\nusb_read: udev %d\n", block_dev->devnum);
+ udev = usb_dev_desc[block_dev->devnum].priv;
+ if (!udev) {
+ debug("%s: No device\n", __func__);
return 0;
- ss = (struct us_data *)dev->privptr;
+ }
+#endif
+ ss = (struct us_data *)udev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
- srb->lun = usb_dev_desc[device].lun;
+ srb->lun = block_dev->lun;
buf_addr = (uintptr_t)buffer;
start = blknr;
blks = blkcnt;
- debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
- " buffer %" PRIxPTR "\n", device, start, blks, buf_addr);
+ debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
+ PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
do {
/* If write fails retry for max retry count else
retry_it:
if (smallblks == USB_MAX_XFER_BLK)
usb_show_progress();
- srb->datalen = usb_dev_desc[device].blksz * smallblks;
+ srb->datalen = block_dev->blksz * smallblks;
srb->pdata = (unsigned char *)buf_addr;
if (usb_write_10(srb, ss, start, smallblks)) {
debug("Write ERROR\n");
struct usb_endpoint_descriptor *ep_desc;
unsigned int flags = 0;
- int protocol = 0;
- int subclass = 0;
-
/* let's examine the device now */
iface = &dev->config.if_desc[ifnum];
-#if 0
- /* this is the place to patch some storage devices */
- debug("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
- dev->descriptor.idProduct);
-
- if ((dev->descriptor.idVendor) == 0x066b &&
- (dev->descriptor.idProduct) == 0x0103) {
- debug("patched for E-USB\n");
- protocol = US_PR_CB;
- subclass = US_SC_UFI; /* an assumption */
- }
-#endif
-
if (dev->descriptor.bDeviceClass != 0 ||
iface->desc.bInterfaceClass != USB_CLASS_MASS_STORAGE ||
iface->desc.bInterfaceSubClass < US_SC_MIN ||
ss->ifnum = ifnum;
ss->pusb_dev = dev;
ss->attention_done = 0;
-
- /* If the device has subclass and protocol, then use that. Otherwise,
- * take data from the specific interface.
- */
- if (subclass) {
- ss->subclass = subclass;
- ss->protocol = protocol;
- } else {
- ss->subclass = iface->desc.bInterfaceSubClass;
- ss->protocol = iface->desc.bInterfaceProtocol;
- }
+ ss->subclass = iface->desc.bInterfaceSubClass;
+ ss->protocol = iface->desc.bInterfaceProtocol;
/* set the handler pointers based on the protocol */
debug("Transport: ");
}
int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
- block_dev_desc_t *dev_desc)
+ struct blk_desc *dev_desc)
{
unsigned char perq, modi;
ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
dev_desc->log2blksz = LOG2(dev_desc->blksz);
dev_desc->type = perq;
debug(" address %d\n", dev_desc->target);
- debug("partype: %d\n", dev_desc->part_type);
- init_part(dev_desc);
-
- debug("partype: %d\n", dev_desc->part_type);
return 1;
}
static int usb_mass_storage_probe(struct udevice *dev)
{
- struct usb_device *udev = dev_get_parentdata(dev);
+ struct usb_device *udev = dev_get_parent_priv(dev);
int ret;
usb_disable_asynch(1); /* asynch transfer not allowed */
.id = UCLASS_MASS_STORAGE,
.of_match = usb_mass_storage_ids,
.probe = usb_mass_storage_probe,
+#ifdef CONFIG_BLK
+ .platdata_auto_alloc_size = sizeof(struct us_data),
+#endif
};
UCLASS_DRIVER(usb_mass_storage) = {
};
U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
+#endif
+
+#ifdef CONFIG_BLK
+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,
+};
+#else
+U_BOOT_LEGACY_BLK(usb) = {
+ .if_typename = "usb",
+ .if_type = IF_TYPE_USB,
+ .max_devs = USB_MAX_STOR_DEV,
+ .desc = usb_dev_desc,
+};
#endif