[SeaBIOS] [PATCH] Support USB MSC devices with multiples LUNs

Kevin O'Connor kevin at koconnor.net
Tue Jun 12 03:32:50 CEST 2012


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 <svens at stackframe.org>

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
-------------- next part --------------
>From 7c1a8f06d797829da00b553c40e1bcf14365d22e Mon Sep 17 00:00:00 2001
From: Sven Schnelle <svens at stackframe.org>
Date: Sun, 10 Jun 2012 18:58:34 +0200
Subject: [PATCH] Support USB MSC devices with multiples LUNs
To: seabios at seabios.org

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 <svens at stackframe.org>
Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 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 at i0cf8/usb at 1,2/hub at 1/network at 0/ethernet at 0
+    // Find usb - for example: /pci at i0cf8/usb at 1,2/storage at 1/channel at 0/disk at 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



More information about the SeaBIOS mailing list