[SeaBIOS] [PATCH 06/19] usb: Obtain free list items in main code.

Kevin O'Connor kevin at koconnor.net
Sun Mar 11 03:43:40 CET 2012


Each controller freelist finding code is the same - move it to the
common code.  This also merges the alloc_control and alloc_bulk code
paths.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/usb-ehci.c |   35 ++++-------------------------------
 src/usb-ehci.h |    3 +--
 src/usb-ohci.c |   27 ++++++---------------------
 src/usb-ohci.h |    3 +--
 src/usb-uhci.c |   37 +++++--------------------------------
 src/usb-uhci.h |    3 +--
 src/usb.c      |   41 +++++++++++++++++++++++++----------------
 src/usb.h      |    1 +
 8 files changed, 44 insertions(+), 106 deletions(-)

diff --git a/src/usb-ehci.c b/src/usb-ehci.c
index 0678560..6115610 100644
--- a/src/usb-ehci.c
+++ b/src/usb-ehci.c
@@ -31,7 +31,6 @@ struct ehci_pipe {
     struct ehci_qtd *next_td, *tds;
     void *data;
     struct usb_pipe pipe;
-    u8 iscontrol;
 };
 
 
@@ -422,31 +421,18 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout)
     return 0;
 }
 
-static struct usb_pipe *
-ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
+struct usb_pipe *
+ehci_alloc_async_pipe(struct usb_pipe *dummy)
 {
     if (! CONFIG_USB_EHCI)
         return NULL;
     struct usb_ehci_s *cntl = container_of(
         dummy->cntl, struct usb_ehci_s, usb);
-    dprintf(7, "ehci_alloc_pipe %p %d\n", &cntl->usb, iscontrol);
-
-    struct usb_pipe *freepipe = cntl->usb.freelist;
-    while (freepipe) {
-        struct ehci_pipe *pipe = container_of(cntl->usb.freelist
-                                              , struct ehci_pipe, pipe);
-        if (pipe->iscontrol == iscontrol) {
-            // Use previously allocated queue head.
-            cntl->usb.freelist = pipe->pipe.freenext;
-            memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
-            return &pipe->pipe;
-        }
-        freepipe = freepipe->freenext;
-    }
+    dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
 
     // Allocate a new queue head.
     struct ehci_pipe *pipe;
-    if (iscontrol)
+    if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
         pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
     else
         pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
@@ -457,7 +443,6 @@ ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
     memset(pipe, 0, sizeof(*pipe));
     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
     pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
-    pipe->iscontrol = iscontrol;
 
     // Add queue head to controller list.
     struct ehci_qh *async_qh = cntl->async_qh;
@@ -467,18 +452,6 @@ ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
     return &pipe->pipe;
 }
 
-struct usb_pipe *
-ehci_alloc_control_pipe(struct usb_pipe *dummy)
-{
-    return ehci_alloc_pipe(dummy, 1);
-}
-
-struct usb_pipe *
-ehci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
-    return ehci_alloc_pipe(dummy, 0);
-}
-
 static int
 fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes)
 {
diff --git a/src/usb-ehci.h b/src/usb-ehci.h
index fd38b73..a4fbb77 100644
--- a/src/usb-ehci.h
+++ b/src/usb-ehci.h
@@ -4,10 +4,9 @@
 // usb-ehci.c
 int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci);
 struct usb_pipe;
-struct usb_pipe *ehci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *ehci_alloc_async_pipe(struct usb_pipe *dummy);
 int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
                  , void *data, int datasize);
-struct usb_pipe *ehci_alloc_bulk_pipe(struct usb_pipe *dummy);
 int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
 struct usb_pipe *ehci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
 int ehci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-ohci.c b/src/usb-ohci.c
index d77727e..9522309 100644
--- a/src/usb-ohci.c
+++ b/src/usb-ohci.c
@@ -319,23 +319,17 @@ wait_ed(struct ohci_ed *ed)
 }
 
 struct usb_pipe *
-ohci_alloc_control_pipe(struct usb_pipe *dummy)
+ohci_alloc_async_pipe(struct usb_pipe *dummy)
 {
     if (! CONFIG_USB_OHCI)
         return NULL;
+    if (dummy->eptype != USB_ENDPOINT_XFER_CONTROL) {
+        dprintf(1, "OHCI Bulk transfers not supported.\n");
+        return NULL;
+    }
     struct usb_ohci_s *cntl = container_of(
         dummy->cntl, struct usb_ohci_s, usb);
-    dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb);
-
-    if (cntl->usb.freelist) {
-        // Use previously allocated queue head.
-        struct ohci_pipe *pipe = container_of(cntl->usb.freelist
-                                              , struct ohci_pipe, pipe);
-        cntl->usb.freelist = pipe->pipe.freenext;
-
-        memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
-        return &pipe->pipe;
-    }
+    dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
 
     // Allocate a new queue head.
     struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
@@ -415,15 +409,6 @@ ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
     return ret;
 }
 
-struct usb_pipe *
-ohci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
-    if (! CONFIG_USB_OHCI)
-        return NULL;
-    dprintf(1, "OHCI Bulk transfers not supported.\n");
-    return NULL;
-}
-
 int
 ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
 {
diff --git a/src/usb-ohci.h b/src/usb-ohci.h
index 6162d32..6085355 100644
--- a/src/usb-ohci.h
+++ b/src/usb-ohci.h
@@ -4,10 +4,9 @@
 // usb-ohci.c
 void ohci_init(struct pci_device *pci, int busid);
 struct usb_pipe;
-struct usb_pipe *ohci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *ohci_alloc_async_pipe(struct usb_pipe *dummy);
 int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
                  , void *data, int datasize);
-struct usb_pipe *ohci_alloc_bulk_pipe(struct usb_pipe *dummy);
 int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
 struct usb_pipe *ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
 int ohci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-uhci.c b/src/usb-uhci.c
index 9d46762..1c911c6 100644
--- a/src/usb-uhci.c
+++ b/src/usb-uhci.c
@@ -26,7 +26,6 @@ struct uhci_pipe {
     struct usb_pipe pipe;
     u16 iobase;
     u8 toggle;
-    u8 iscontrol;
 };
 
 
@@ -293,31 +292,18 @@ wait_pipe(struct uhci_pipe *pipe, int timeout)
     }
 }
 
-static struct usb_pipe *
-uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
+struct usb_pipe *
+uhci_alloc_async_pipe(struct usb_pipe *dummy)
 {
     if (! CONFIG_USB_UHCI)
         return NULL;
     struct usb_uhci_s *cntl = container_of(
         dummy->cntl, struct usb_uhci_s, usb);
-    dprintf(7, "uhci_alloc_pipe %p %d\n", &cntl->usb, iscontrol);
-
-    struct usb_pipe *freepipe = cntl->usb.freelist;
-    while (freepipe) {
-        struct uhci_pipe *pipe = container_of(cntl->usb.freelist
-                                              , struct uhci_pipe, pipe);
-        if (pipe->iscontrol == iscontrol) {
-            // Use previously allocated queue head.
-            cntl->usb.freelist = pipe->pipe.freenext;
-            memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
-            return &pipe->pipe;
-        }
-        freepipe = freepipe->freenext;
-    }
+    dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
 
     // Allocate a new queue head.
     struct uhci_pipe *pipe;
-    if (iscontrol)
+    if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
         pipe = malloc_tmphigh(sizeof(*pipe));
     else
         pipe = malloc_low(sizeof(*pipe));
@@ -329,30 +315,17 @@ uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
     pipe->qh.element = UHCI_PTR_TERM;
     pipe->iobase = cntl->iobase;
-    pipe->iscontrol = iscontrol;
 
     // Add queue head to controller list.
     struct uhci_qh *control_qh = cntl->control_qh;
     pipe->qh.link = control_qh->link;
     barrier();
     control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
-    if (iscontrol)
+    if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
         cntl->control_qh = &pipe->qh;
     return &pipe->pipe;
 }
 
-struct usb_pipe *
-uhci_alloc_control_pipe(struct usb_pipe *dummy)
-{
-    return uhci_alloc_pipe(dummy, 1);
-}
-
-struct usb_pipe *
-uhci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
-    return uhci_alloc_pipe(dummy, 0);
-}
-
 int
 uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
              , void *data, int datasize)
diff --git a/src/usb-uhci.h b/src/usb-uhci.h
index 59b190d..0706e8f 100644
--- a/src/usb-uhci.h
+++ b/src/usb-uhci.h
@@ -4,10 +4,9 @@
 // usb-uhci.c
 void uhci_init(struct pci_device *pci, int busid);
 struct usb_pipe;
-struct usb_pipe *uhci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *uhci_alloc_async_pipe(struct usb_pipe *dummy);
 int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
                  , void *data, int datasize);
-struct usb_pipe *uhci_alloc_bulk_pipe(struct usb_pipe *dummy);
 int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
 struct usb_pipe *uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
 int uhci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb.c b/src/usb.c
index e7ee6bc..7c49c6a 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -36,19 +36,34 @@ free_pipe(struct usb_pipe *pipe)
     cntl->freelist = pipe;
 }
 
-// Allocate a control pipe to a default endpoint (which can only be
-// used by 32bit code)
+// Allocate an async pipe (control or bulk).
 static struct usb_pipe *
-alloc_default_control_pipe(struct usb_pipe *dummy)
+alloc_async_pipe(struct usb_pipe *dummy)
 {
+    // Check for an available pipe on the freelist.
+    struct usb_pipe **pfree = &dummy->cntl->freelist;
+    for (;;) {
+        struct usb_pipe *pipe = *pfree;
+        if (!pipe)
+            break;
+        if (pipe->eptype == dummy->eptype) {
+            // Use previously allocated pipe.
+            *pfree = pipe->freenext;
+            memcpy(pipe, dummy, sizeof(*pipe));
+            return pipe;
+        }
+        pfree = &pipe->freenext;
+    }
+
+    // Allocate a new pipe.
     switch (dummy->type) {
     default:
     case USB_TYPE_UHCI:
-        return uhci_alloc_control_pipe(dummy);
+        return uhci_alloc_async_pipe(dummy);
     case USB_TYPE_OHCI:
-        return ohci_alloc_control_pipe(dummy);
+        return ohci_alloc_async_pipe(dummy);
     case USB_TYPE_EHCI:
-        return ehci_alloc_control_pipe(dummy);
+        return ehci_alloc_async_pipe(dummy);
     }
 }
 
@@ -84,15 +99,8 @@ alloc_bulk_pipe(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc)
 {
     struct usb_pipe dummy;
     desc2pipe(&dummy, pipe, epdesc);
-    switch (pipe->type) {
-    default:
-    case USB_TYPE_UHCI:
-        return uhci_alloc_bulk_pipe(&dummy);
-    case USB_TYPE_OHCI:
-        return ohci_alloc_bulk_pipe(&dummy);
-    case USB_TYPE_EHCI:
-        return ehci_alloc_bulk_pipe(&dummy);
-    }
+    dummy.eptype = USB_ENDPOINT_XFER_BULK;
+    return alloc_async_pipe(&dummy);
 }
 
 int
@@ -253,7 +261,8 @@ usb_set_address(struct usbhub_s *hub, int port, int speed)
     dummy.type = cntl->type;
     dummy.maxpacket = 8;
     dummy.path = (u64)-1;
-    struct usb_pipe *defpipe = alloc_default_control_pipe(&dummy);
+    dummy.eptype = USB_ENDPOINT_XFER_CONTROL;
+    struct usb_pipe *defpipe = alloc_async_pipe(&dummy);
     if (!defpipe)
         return NULL;
     defpipe->speed = speed;
diff --git a/src/usb.h b/src/usb.h
index 47b25b6..44f8a96 100644
--- a/src/usb.h
+++ b/src/usb.h
@@ -18,6 +18,7 @@ struct usb_pipe {
     u16 maxpacket;
     u8 tt_devaddr;
     u8 tt_port;
+    u8 eptype;
 };
 
 // Common information for usb controllers.
-- 
1.7.6.5




More information about the SeaBIOS mailing list