[SeaBIOS] [PATCH] Refactor USB hub code.

Kevin O'Connor kevin at koconnor.net
Sat Apr 3 02:14:50 CEST 2010


All four implementations of hubs (and root hubs) were very similar.
Replace them with a single implementation that uses callbacks for the
three custom parts (detect, reset, disconnect) of each type of hub.
---
 src/usb-ehci.c |  100 ++++++++++++++++++++++++++---------------------------
 src/usb-hub.c  |  106 ++++++++++++++++++++++++++-----------------------------
 src/usb-hub.h  |   10 -----
 src/usb-ohci.c |   82 ++++++++++++++++++-------------------------
 src/usb-uhci.c |   75 ++++++++++++++++++---------------------
 src/usb.c      |   64 ++++++++++++++++++++++++++++++++-
 src/usb.h      |   25 ++++++++++++--
 7 files changed, 253 insertions(+), 209 deletions(-)

diff --git a/src/usb-ehci.c b/src/usb-ehci.c
index 8e3219f..1f683c8 100644
--- a/src/usb-ehci.c
+++ b/src/usb-ehci.c
@@ -13,7 +13,6 @@
 #include "pci_regs.h" // PCI_BASE_ADDRESS_0
 #include "usb.h" // struct usb_s
 #include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
 #include "usb-uhci.h" // init_uhci
 #include "usb-ohci.h" // init_ohci
 
@@ -40,13 +39,17 @@ struct usb_ehci_s {
 #define EHCI_TIME_POSTPOWER 20
 #define EHCI_TIME_POSTRESET 2
 
-// Start processing of companion controllers for full/low speed devices
+// Check if need companion controllers for full/low speed devices
 static void
-ehci_startcompanion(struct usb_ehci_s *cntl)
+ehci_note_port(struct usb_ehci_s *cntl)
 {
+    if (--cntl->checkports)
+        // Ports still being detected.
+        return;
     if (! cntl->legacycount)
         // No full/low speed devices found.
         return;
+    // Start companion controllers.
     int i;
     for (i=0; i<ARRAY_SIZE(cntl->companion); i++) {
         u16 type = cntl->companion[i].type;
@@ -59,13 +62,11 @@ ehci_startcompanion(struct usb_ehci_s *cntl)
     }
 }
 
-static void
-init_ehci_port(void *data)
+// Check if device attached to port
+static int
+ehci_hub_detect(struct usbhub_s *hub, u32 port)
 {
-    struct usbhub_s *hub = data;
-    u32 port = hub->port; // XXX - find better way to pass port
     struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
-
     u32 *portreg = &cntl->regs->portsc[port];
     u32 portsc = readl(portreg);
 
@@ -92,15 +93,31 @@ init_ehci_port(void *data)
 
     // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
 
-    // Reset port
+    // Begin reset on port
     portsc = (portsc & ~PORT_PE) | PORT_RESET;
     writel(portreg, portsc);
     msleep(USB_TIME_DRSTR);
-    mutex_lock(&cntl->usb.resetlock);
+    return 0;
+
+doneearly:
+    ehci_note_port(cntl);
+    return -1;
+}
+
+// Reset device on port
+static int
+ehci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+    u32 *portreg = &cntl->regs->portsc[port];
+    u32 portsc = readl(portreg);
+
+    // Finish reset on port
     portsc &= ~PORT_RESET;
     writel(portreg, portsc);
     msleep(EHCI_TIME_POSTRESET);
 
+    int rv = -1;
     portsc = readl(portreg);
     if (!(portsc & PORT_CONNECT))
         // No longer connected
@@ -112,58 +129,39 @@ init_ehci_port(void *data)
         goto resetfail;
     }
 
-    if (! --cntl->checkports)
-        ehci_startcompanion(cntl);
-
-    struct usb_pipe *pipe = usb_set_address(hub, port, USB_HIGHSPEED);
-    if (!pipe) {
-        writel(portreg, portsc & ~PORT_PE);
-        mutex_unlock(&cntl->usb.resetlock);
-        goto done;
-    }
-    mutex_unlock(&cntl->usb.resetlock);
-
-    // Configure port
-    int count = configure_usb_device(pipe);
-    free_pipe(pipe);
-    if (! count)
-        // Disable port
-        writel(portreg, portsc & ~PORT_PE);
-    hub->devcount += count;
-done:
-    hub->threads--;
-    return;
-
+    rv = USB_HIGHSPEED;
 resetfail:
-    mutex_unlock(&cntl->usb.resetlock);
-doneearly:
-    if (! --cntl->checkports)
-        ehci_startcompanion(cntl);
-    goto done;
+    ehci_note_port(cntl);
+    return rv;
+}
+
+// Disable port
+static void
+ehci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+    u32 *portreg = &cntl->regs->portsc[port];
+    u32 portsc = readl(portreg);
+    writel(portreg, portsc & ~PORT_PE);
 }
 
+static struct usbhub_op_s ehci_HubOp = {
+    .detect = ehci_hub_detect,
+    .reset = ehci_hub_reset,
+    .disconnect = ehci_hub_disconnect,
+};
+
 // Find any devices connected to the root hub.
 static int
 check_ehci_ports(struct usb_ehci_s *cntl)
 {
     ASSERT32FLAT();
-
-    // Launch a thread for every port.
     struct usbhub_s hub;
     memset(&hub, 0, sizeof(hub));
     hub.cntl = &cntl->usb;
-    int ports = cntl->checkports;
-    hub.threads = ports;
-    int i;
-    for (i=0; i<ports; i++) {
-        hub.port = i;
-        run_thread(init_ehci_port, &hub);
-    }
-
-    // Wait for threads to complete.
-    while (hub.threads)
-        yield();
-
+    hub.portcount = cntl->checkports;
+    hub.op = &ehci_HubOp;
+    usb_enumerate(&hub);
     return hub.devcount;
 }
 
diff --git a/src/usb-hub.c b/src/usb-hub.c
index 9effbc3..1586bac 100644
--- a/src/usb-hub.c
+++ b/src/usb-hub.c
@@ -28,7 +28,7 @@ set_port_feature(struct usbhub_s *hub, int port, int feature)
     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
     req.bRequest = USB_REQ_SET_FEATURE;
     req.wValue = feature;
-    req.wIndex = port;
+    req.wIndex = port + 1;
     req.wLength = 0;
     mutex_lock(&hub->lock);
     int ret = send_default_control(hub->pipe, &req, NULL);
@@ -43,7 +43,7 @@ clear_port_feature(struct usbhub_s *hub, int port, int feature)
     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
     req.bRequest = USB_REQ_CLEAR_FEATURE;
     req.wValue = feature;
-    req.wIndex = port;
+    req.wIndex = port + 1;
     req.wLength = 0;
     mutex_lock(&hub->lock);
     int ret = send_default_control(hub->pipe, &req, NULL);
@@ -58,7 +58,7 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
     req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
     req.bRequest = USB_REQ_GET_STATUS;
     req.wValue = 0;
-    req.wIndex = port;
+    req.wIndex = port + 1;
     req.wLength = sizeof(*sts);
     mutex_lock(&hub->lock);
     int ret = send_default_control(hub->pipe, &req, sts);
@@ -66,12 +66,10 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
     return ret;
 }
 
-static void
-init_hub_port(void *data)
+// Check if device attached to port
+static int
+usb_hub_detect(struct usbhub_s *hub, u32 port)
 {
-    struct usbhub_s *hub = data;
-    u32 port = hub->port; // XXX - find better way to pass port
-
     // Turn on power to port.
     int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER);
     if (ret)
@@ -92,29 +90,48 @@ init_hub_port(void *data)
             break;
         if (check_time(end))
             // No device found.
-            goto done;
+            return -1;
         msleep(5);
     }
 
     // XXX - wait USB_TIME_ATTDB time?
 
-    // Reset port.
-    mutex_lock(&hub->cntl->resetlock);
-    ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
+    return 0;
+
+fail:
+    dprintf(1, "Failure on hub port %d detect\n", port);
+    return -1;
+}
+
+// Disable port
+static void
+usb_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
+    if (ret)
+        dprintf(1, "Failure on hub port %d disconnect\n", port);
+}
+
+// Reset device on port
+static int
+usb_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
     if (ret)
-        goto resetfail;
+        goto fail;
 
     // Wait for reset to complete.
-    end = calc_future_tsc(USB_TIME_DRST * 2);
+    struct usb_port_status sts;
+    u64 end = calc_future_tsc(USB_TIME_DRST * 2);
     for (;;) {
         ret = get_port_status(hub, port, &sts);
         if (ret)
-            goto resetfail;
+            goto fail;
         if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
             break;
         if (check_time(end)) {
             warn_timeout();
-            goto resetfail;
+            goto fail;
         }
         msleep(5);
     }
@@ -122,37 +139,23 @@ init_hub_port(void *data)
     // Reset complete.
     if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION))
         // Device no longer present
-        goto resetfail;
-
-    // Set address of port
-    struct usb_pipe *pipe = usb_set_address(
-        hub, port, ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
-                    >> USB_PORT_STAT_SPEED_SHIFT));
-    if (!pipe)
-        goto resetfail;
-    mutex_unlock(&hub->cntl->resetlock);
-
-    // Configure the device
-    int count = configure_usb_device(pipe);
-    free_pipe(pipe);
-    if (!count) {
-        ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
-        if (ret)
-            goto fail;
-    }
-    hub->devcount += count;
-done:
-    hub->threads--;
-    return;
-
-resetfail:
-    clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
-    mutex_unlock(&hub->cntl->resetlock);
+        return -1;
+
+    return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
+            >> USB_PORT_STAT_SPEED_SHIFT);
+
 fail:
-    dprintf(1, "Failure on hub port %d setup\n", port);
-    goto done;
+    dprintf(1, "Failure on hub port %d reset\n", port);
+    usb_hub_disconnect(hub, port);
+    return -1;
 }
 
+static struct usbhub_op_s HubOp = {
+    .detect = usb_hub_detect,
+    .reset = usb_hub_reset,
+    .disconnect = usb_hub_disconnect,
+};
+
 // Configure a usb hub and then find devices connected to it.
 int
 usb_hub_init(struct usb_pipe *pipe)
@@ -171,18 +174,9 @@ usb_hub_init(struct usb_pipe *pipe)
     hub.pipe = pipe;
     hub.cntl = pipe->cntl;
     hub.powerwait = desc.bPwrOn2PwrGood * 2;
-
-    // Launch a thread for every port.
-    int i;
-    for (i=1; i<=desc.bNbrPorts; i++) {
-        hub.port = i;
-        hub.threads++;
-        run_thread(init_hub_port, &hub);
-    }
-
-    // Wait for threads to complete.
-    while (hub.threads)
-        yield();
+    hub.portcount = desc.bNbrPorts;
+    hub.op = &HubOp;
+    usb_enumerate(&hub);
 
     dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount);
     if (hub.devcount)
diff --git a/src/usb-hub.h b/src/usb-hub.h
index 0994320..7672028 100644
--- a/src/usb-hub.h
+++ b/src/usb-hub.h
@@ -1,16 +1,6 @@
 #ifndef __USB_HUB_H
 #define __USB_HUB_H
 
-struct usbhub_s {
-    struct usb_pipe *pipe;
-    struct usb_s *cntl;
-    struct mutex_s lock;
-    u32 powerwait;
-    u32 port;
-    u32 threads;
-    u32 devcount;
-};
-
 // usb-hub.c
 struct usb_pipe;
 int usb_hub_init(struct usb_pipe *pipe);
diff --git a/src/usb-ohci.c b/src/usb-ohci.c
index 71ae561..43fe238 100644
--- a/src/usb-ohci.c
+++ b/src/usb-ohci.c
@@ -11,7 +11,6 @@
 #include "pci_regs.h" // PCI_BASE_ADDRESS_0
 #include "usb.h" // struct usb_s
 #include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
 
 #define FIT                     (1 << 31)
 
@@ -25,23 +24,36 @@ struct usb_ohci_s {
  * Root hub
  ****************************************************************/
 
-static void
-init_ohci_port(void *data)
+// Check if device attached to port
+static int
+ohci_hub_detect(struct usbhub_s *hub, u32 port)
 {
-    struct usbhub_s *hub = data;
-    u32 port = hub->port; // XXX - find better way to pass port
     struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
-
     u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
     if (!(sts & RH_PS_CCS))
         // No device.
-        goto done;
+        return -1;
 
     // XXX - need to wait for USB_TIME_ATTDB if just powered up?
 
-    // Signal reset
-    mutex_lock(&cntl->usb.resetlock);
+    return 0;
+}
+
+// Disable port
+static void
+ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
+    writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
+}
+
+// Reset device on port
+static int
+ohci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
     writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
+    u32 sts;
     u64 end = calc_future_tsc(USB_TIME_DRSTR * 2);
     for (;;) {
         sts = readl(&cntl->regs->roothub_portstatus[port]);
@@ -51,39 +63,25 @@ init_ohci_port(void *data)
         if (check_time(end)) {
             // Timeout.
             warn_timeout();
-            goto resetfail;
+            ohci_hub_disconnect(hub, port);
+            return -1;
         }
         yield();
     }
 
     if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
         // Device no longer present
-        goto resetfail;
-
-    // Set address of port
-    struct usb_pipe *pipe = usb_set_address(hub, port, !!(sts & RH_PS_LSDA));
-    if (!pipe)
-        goto resetfail;
-    mutex_unlock(&cntl->usb.resetlock);
-
-    // Configure the device
-    int count = configure_usb_device(pipe);
-    free_pipe(pipe);
-    if (! count)
-        // Shutdown port
-        writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
-    hub->devcount += count;
-done:
-    hub->threads--;
-    return;
+        return -1;
 
-resetfail:
-    // Shutdown port
-    writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
-    mutex_unlock(&cntl->usb.resetlock);
-    goto done;
+    return !!(sts & RH_PS_LSDA);
 }
 
+static struct usbhub_op_s ohci_HubOp = {
+    .detect = ohci_hub_detect,
+    .reset = ohci_hub_reset,
+    .disconnect = ohci_hub_disconnect,
+};
+
 // Find any devices connected to the root hub.
 static int
 check_ohci_ports(struct usb_ohci_s *cntl)
@@ -97,22 +95,12 @@ check_ohci_ports(struct usb_ohci_s *cntl)
     msleep((rha >> 24) * 2);
     // XXX - need to sleep for USB_TIME_SIGATT if just powered up?
 
-    // Lanuch a thread per port.
     struct usbhub_s hub;
     memset(&hub, 0, sizeof(hub));
     hub.cntl = &cntl->usb;
-    int ports = rha & RH_A_NDP;
-    hub.threads = ports;
-    int i;
-    for (i=0; i<ports; i++) {
-        hub.port = i;
-        run_thread(init_ohci_port, &hub);
-    }
-
-    // Wait for threads to complete.
-    while (hub.threads)
-        yield();
-
+    hub.portcount = rha & RH_A_NDP;
+    hub.op = &ohci_HubOp;
+    usb_enumerate(&hub);
     return hub.devcount;
 }
 
diff --git a/src/usb-uhci.c b/src/usb-uhci.c
index 4e0c276..b05e09a 100644
--- a/src/usb-uhci.c
+++ b/src/usb-uhci.c
@@ -12,7 +12,6 @@
 #include "pci_regs.h" // PCI_BASE_ADDRESS_4
 #include "usb.h" // struct usb_s
 #include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
 
 struct usb_uhci_s {
     struct usb_s usb;
@@ -26,55 +25,59 @@ struct usb_uhci_s {
  * Root hub
  ****************************************************************/
 
-static void
-init_uhci_port(void *data)
+// Check if device attached to a given port
+static int
+uhci_hub_detect(struct usbhub_s *hub, u32 port)
 {
-    struct usbhub_s *hub = data;
-    u32 port = hub->port; // XXX - find better way to pass port
     struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
     u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
 
     u16 status = inw(ioport);
     if (!(status & USBPORTSC_CCS))
         // No device
-        goto done;
+        return -1;
 
     // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
 
-    // Reset port
+    // Begin reset on port
     outw(USBPORTSC_PR, ioport);
     msleep(USB_TIME_DRSTR);
-    mutex_lock(&cntl->usb.resetlock);
+    return 0;
+}
+
+// Reset device on port
+static int
+uhci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
+
+    // Finish reset on port
     outw(0, ioport);
     udelay(6); // 64 high-speed bit times
-    status = inw(ioport);
+    u16 status = inw(ioport);
     if (!(status & USBPORTSC_CCS))
         // No longer connected
-        goto resetfail;
+        return -1;
     outw(USBPORTSC_PE, ioport);
-    struct usb_pipe *pipe = usb_set_address(
-        hub, port, !!(status & USBPORTSC_LSDA));
-    if (!pipe)
-        goto resetfail;
-    mutex_unlock(&cntl->usb.resetlock);
-
-    // Configure port
-    int count = configure_usb_device(pipe);
-    free_pipe(pipe);
-    if (! count)
-        // Disable port
-        outw(0, ioport);
-    hub->devcount += count;
-done:
-    hub->threads--;
-    return;
-
-resetfail:
+    return !!(status & USBPORTSC_LSDA);
+}
+
+// Disable port
+static void
+uhci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+    struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+    u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
     outw(0, ioport);
-    mutex_unlock(&cntl->usb.resetlock);
-    goto done;
 }
 
+static struct usbhub_op_s uhci_HubOp = {
+    .detect = uhci_hub_detect,
+    .reset = uhci_hub_reset,
+    .disconnect = uhci_hub_disconnect,
+};
+
 // Find any devices connected to the root hub.
 static int
 check_uhci_ports(struct usb_uhci_s *cntl)
@@ -83,17 +86,9 @@ check_uhci_ports(struct usb_uhci_s *cntl)
     struct usbhub_s hub;
     memset(&hub, 0, sizeof(hub));
     hub.cntl = &cntl->usb;
-    hub.threads = 2;
-
-    // Launch a thread for every port.
-    run_thread(init_uhci_port, &hub);
-    hub.port = 1;
-    run_thread(init_uhci_port, &hub);
-
-    // Wait for threads to complete.
-    while (hub.threads)
-        yield();
-
+    hub.portcount = 2;
+    hub.op = &uhci_HubOp;
+    usb_enumerate(&hub);
     return hub.devcount;
 }
 
diff --git a/src/usb.c b/src/usb.c
index 8b3c36e..694ea28 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -242,7 +242,7 @@ set_configuration(struct usb_pipe *pipe, u16 val)
 
 // Assign an address to a device in the default state on the given
 // controller.
-struct usb_pipe *
+static struct usb_pipe *
 usb_set_address(struct usbhub_s *hub, int port, int speed)
 {
     ASSERT32FLAT();
@@ -299,7 +299,7 @@ usb_set_address(struct usbhub_s *hub, int port, int speed)
 
 // Called for every found device - see if a driver is available for
 // this device and do setup if so.
-int
+static int
 configure_usb_device(struct usb_pipe *pipe)
 {
     ASSERT32FLAT();
@@ -356,6 +356,66 @@ fail:
     return 0;
 }
 
+static void
+usb_init_hub_port(void *data)
+{
+    struct usbhub_s *hub = data;
+    u32 port = hub->port; // XXX - find better way to pass port
+
+    // Detect if device present (and possibly start reset)
+    int ret = hub->op->detect(hub, port);
+    if (ret)
+        // No device present
+        goto done;
+
+    // Reset port and determine device speed
+    mutex_lock(&hub->cntl->resetlock);
+    ret = hub->op->reset(hub, port);
+    if (ret < 0)
+        // Reset failed
+        goto resetfail;
+
+    // Set address of port
+    struct usb_pipe *pipe = usb_set_address(hub, port, ret);
+    if (!pipe) {
+        hub->op->disconnect(hub, port);
+        goto resetfail;
+    }
+    mutex_unlock(&hub->cntl->resetlock);
+
+    // Configure the device
+    int count = configure_usb_device(pipe);
+    free_pipe(pipe);
+    if (!count)
+        hub->op->disconnect(hub, port);
+    hub->devcount += count;
+done:
+    hub->threads--;
+    return;
+
+resetfail:
+    mutex_unlock(&hub->cntl->resetlock);
+    goto done;
+}
+
+void
+usb_enumerate(struct usbhub_s *hub)
+{
+    u32 portcount = hub->portcount;
+    hub->threads = portcount;
+
+    // Launch a thread for every port.
+    int i;
+    for (i=0; i<portcount; i++) {
+        hub->port = i;
+        run_thread(usb_init_hub_port, hub);
+    }
+
+    // Wait for threads to complete.
+    while (hub->threads)
+        yield();
+}
+
 void
 usb_setup(void)
 {
diff --git a/src/usb.h b/src/usb.h
index b5cbf2e..f28a3a7 100644
--- a/src/usb.h
+++ b/src/usb.h
@@ -4,6 +4,7 @@
 
 #include "util.h" // struct mutex_s
 
+// Information on a USB end point.
 struct usb_pipe {
     struct usb_s *cntl;
     u8 type;
@@ -24,6 +25,26 @@ struct usb_s {
     u8 maxaddr;
 };
 
+// Information for enumerating USB hubs
+struct usbhub_s {
+    struct usbhub_op_s *op;
+    struct usb_pipe *pipe;
+    struct usb_s *cntl;
+    struct mutex_s lock;
+    u32 powerwait;
+    u32 port;
+    u32 threads;
+    u32 portcount;
+    u32 devcount;
+};
+
+// Hub callback (32bit) info
+struct usbhub_op_s {
+    int (*detect)(struct usbhub_s *hub, u32 port);
+    int (*reset)(struct usbhub_s *hub, u32 port);
+    void (*disconnect)(struct usbhub_s *hub, u32 port);
+};
+
 #define USB_TYPE_UHCI 1
 #define USB_TYPE_OHCI 2
 #define USB_TYPE_EHCI 3
@@ -175,9 +196,7 @@ struct usb_endpoint_descriptor {
 
 // usb.c
 void usb_setup(void);
-struct usbhub_s;
-struct usb_pipe *usb_set_address(struct usbhub_s *hub, int port, int speed);
-int configure_usb_device(struct usb_pipe *pipe);
+void usb_enumerate(struct usbhub_s *hub);
 int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
                          , void *data);
 int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize);
-- 
1.6.6.1




More information about the SeaBIOS mailing list