[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