On Sun, Jun 10, 2012 at 06:58:34PM +0200, Sven Schnelle wrote:
> There are USB Mass storage devices which have more than one device.
> Examples are CD Changers, or USB sticks which are partitioned in a
> CDROM and Harddisk device.
> 
> Signed-off-by: Sven Schnelle <[email protected]>

Thanks.  The main part of the patch looks good, but the patch also
includes some style changes as well.  Also, it doesn't update the boot
priority code.  How about the attached instead?

-Kevin
>From 7c1a8f06d797829da00b553c40e1bcf14365d22e Mon Sep 17 00:00:00 2001
From: Sven Schnelle <[email protected]>
Date: Sun, 10 Jun 2012 18:58:34 +0200
Subject: [PATCH] Support USB MSC devices with multiples LUNs
To: [email protected]

There are USB Mass storage devices which have more than one device.
Examples are CD Changers, or USB sticks which are partitioned in a
CDROM and Harddisk device.

Signed-off-by: Sven Schnelle <[email protected]>
Signed-off-by: Kevin O'Connor <[email protected]>
---
 src/boot.c    |    6 ++--
 src/boot.h    |    2 +-
 src/usb-msc.c |   80 ++++++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/src/boot.c b/src/boot.c
index 6949490..392c692 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -205,15 +205,15 @@ build_usb_path(char *buf, int max, struct usbhub_s *hub)
     return p;
 }
 
-int bootprio_find_usb(struct usbdevice_s *usbdev)
+int bootprio_find_usb(struct usbdevice_s *usbdev, int lun)
 {
     if (!CONFIG_BOOTORDER)
         return -1;
-    // Find usb - for example: /pci@i0cf8/usb@1,2/hub@1/network@0/ethernet@0
+    // Find usb - for example: /pci@i0cf8/usb@1,2/storage@1/channel@0/disk@0,0
     char desc[256], *p;
     p = build_pci_path(desc, sizeof(desc), "usb", usbdev->hub->cntl->pci);
     p = build_usb_path(p, desc+sizeof(desc)-p, usbdev->hub);
-    snprintf(p, desc+sizeof(desc)-p, "/*@%x", usbdev->port+1);
+    snprintf(p, desc+sizeof(desc)-p, "/*@%x/*@0/*@0,%d", usbdev->port+1, lun);
     return find_prio(desc);
 }
 
diff --git a/src/boot.h b/src/boot.h
index c7c34dc..afe9f2e 100644
--- a/src/boot.h
+++ b/src/boot.h
@@ -20,6 +20,6 @@ int bootprio_find_fdc_device(struct pci_device *pci, int 
port, int fdid);
 int bootprio_find_pci_rom(struct pci_device *pci, int instance);
 int bootprio_find_named_rom(const char *name, int instance);
 struct usbdevice_s;
-int bootprio_find_usb(struct usbdevice_s *usbdev);
+int bootprio_find_usb(struct usbdevice_s *usbdev, int lun);
 
 #endif // __BOOT_H
diff --git a/src/usb-msc.c b/src/usb-msc.c
index c53a1f5..46737c0 100644
--- a/src/usb-msc.c
+++ b/src/usb-msc.c
@@ -16,6 +16,7 @@
 struct usbdrive_s {
     struct drive_s drive;
     struct usb_pipe *bulkin, *bulkout;
+    int lun;
 };
 
 
@@ -78,7 +79,7 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 
blocksize)
     cbw.dCBWTag = 999; // XXX
     cbw.dCBWDataTransferLength = bytes;
     cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT;
-    cbw.bCBWLUN = 0; // XXX
+    cbw.bCBWLUN = GET_GLOBAL(udrive_g->lun);
     cbw.bCBWCBLength = USB_CDB_SIZE;
 
     // Transfer cbw to device.
@@ -117,6 +118,48 @@ fail:
     return DISK_RET_EBADTRACK;
 }
 
+static int
+usb_msc_maxlun(struct usb_pipe *pipe)
+{
+    struct usb_ctrlrequest req;
+    req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+    req.bRequest = 0xfe;
+    req.wValue = 0;
+    req.wIndex = 0;
+    req.wLength = 1;
+    unsigned char maxlun;
+    int ret = send_default_control(pipe, &req, &maxlun);
+    if (ret)
+        return 0;
+    return maxlun;
+}
+
+static int
+usb_msc_init_lun(struct usb_pipe *inpipe, struct usb_pipe *outpipe,
+                 struct usbdevice_s *usbdev, int lun)
+{
+    // Allocate drive structure.
+    struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g));
+    if (!udrive_g) {
+        warn_noalloc();
+        return -1;
+    }
+    memset(udrive_g, 0, sizeof(*udrive_g));
+    udrive_g->drive.type = DTYPE_USB;
+    udrive_g->lun = lun;
+
+    udrive_g->bulkin = inpipe;
+    udrive_g->bulkout = outpipe;
+
+    int ret = scsi_init_drive(&udrive_g->drive, "USB MSC"
+                              , bootprio_find_usb(usbdev, lun));
+    if (ret) {
+        dprintf(1, "Unable to configure USB MSC drive.\n");
+        free(udrive_g);
+        return -1;
+    }
+    return 0;
+}
 
 /****************************************************************
  * Setup
@@ -140,39 +183,34 @@ usb_msc_init(struct usbdevice_s *usbdev)
         return -1;
     }
 
-    // Allocate drive structure.
-    struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g));
-    if (!udrive_g) {
-        warn_noalloc();
-        goto fail;
-    }
-    memset(udrive_g, 0, sizeof(*udrive_g));
-    udrive_g->drive.type = DTYPE_USB;
-
     // Find bulk in and bulk out endpoints.
     struct usb_endpoint_descriptor *indesc = findEndPointDesc(
         usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
     struct usb_endpoint_descriptor *outdesc = findEndPointDesc(
         usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
+    struct usb_pipe *inpipe = NULL, *outpipe = NULL;
     if (!indesc || !outdesc)
         goto fail;
-    udrive_g->bulkin = usb_alloc_pipe(usbdev, indesc);
-    udrive_g->bulkout = usb_alloc_pipe(usbdev, outdesc);
-    if (!udrive_g->bulkin || !udrive_g->bulkout)
+    inpipe = usb_alloc_pipe(usbdev, indesc);
+    outpipe = usb_alloc_pipe(usbdev, outdesc);
+    if (!inpipe || !outpipe)
         goto fail;
 
-    int prio = bootprio_find_usb(usbdev);
-    int ret = scsi_init_drive(&udrive_g->drive, "USB MSC", prio);
-    if (ret)
+    int maxlun = usb_msc_maxlun(usbdev->defpipe);
+    int lun, pipesused = 0;
+    for (lun = 0; lun < maxlun + 1; lun++) {
+        int ret = usb_msc_init_lun(inpipe, outpipe, usbdev, lun);
+        if (!ret)
+            pipesused = 1;
+    }
+
+    if (!pipesused)
         goto fail;
 
     return 0;
 fail:
     dprintf(1, "Unable to configure USB MSC device.\n");
-    if (udrive_g) {
-        free_pipe(udrive_g->bulkin);
-        free_pipe(udrive_g->bulkout);
-        free(udrive_g);
-    }
+    free_pipe(inpipe);
+    free_pipe(outpipe);
     return -1;
 }
-- 
1.7.6.5

_______________________________________________
SeaBIOS mailing list
[email protected]
http://www.seabios.org/mailman/listinfo/seabios

Reply via email to