This series updates the USB code. This is mostly a code reorganization, though there are a couple of bug fixes (mostly for OHCI).
-Kevin
Kevin O'Connor (19): Batch free USB pipes on OHCI controllers. Batch free USB pipes on UHCI controllers. Batch free USB pipes on EHCI controllers. usb: Centralize pipe free list code. usb: Remove cntl->defaultpipe cache. usb: Obtain free list items in main code. usb: Introduce 'struct usbdevice_s' to describe info for a given device. usb: Push 'struct usbdevice_s' usage through to pipe allocation. usb: Build path via chain of usbdevice_s. usb: Pass usbdevice_s to alloc_async_pipe. usb: Pass 'struct usbdevice_s' into controller alloc_async functions. usb: Pass 'struct usbdevice_s' to controller alloc_intr_pipe functions. usb: Move code around in usb controller code. usb: Generalize controller alloc_async_pipe / alloc_intr_pipe code. usb: Move code around in usb.c. usb: Move EHCI tt_* fields to EHCI controller code. usb: Populate OHCI endpoint descriptor info at pipe allocation. usb: Fix barrier() placement in OHCI interrupt schedule add. usb: Remove QH_MULT_SHIFT flag from qh.info1.
src/boot.c | 25 ++-- src/boot.h | 3 +- src/usb-ehci.c | 441 +++++++++++++++++++++++++++----------------------------- src/usb-ehci.h | 8 +- src/usb-hid.c | 28 ++-- src/usb-hid.h | 6 +- src/usb-hub.c | 14 +- src/usb-hub.h | 4 +- src/usb-msc.c | 14 +- src/usb-msc.h | 6 +- src/usb-ohci.c | 323 +++++++++++++++++++++--------------------- src/usb-ohci.h | 8 +- src/usb-uhci.c | 411 +++++++++++++++++++++++++--------------------------- src/usb-uhci.h | 8 +- src/usb.c | 277 +++++++++++++++++------------------ src/usb.h | 48 ++++--- 16 files changed, 797 insertions(+), 827 deletions(-)
Instead of unregistering each control "endpoint descriptor" after it is used, keep them around for later users. Free all unused descriptors in one batch at the end of initialization. This should slightly optimize boot time, and it requires less overall interaction with the controller.
This also makes the descriptor free code more compliant with the spec. The descriptor lists will only be modified after the list processing has been disabled on the controller.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ohci.c | 142 +++++++++++++++++++++++++++++-------------------------- src/usb.h | 6 ++- 2 files changed, 80 insertions(+), 68 deletions(-)
diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 9107db2..7a437ad 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -19,6 +19,14 @@ struct usb_ohci_s { struct ohci_regs *regs; };
+struct ohci_pipe { + struct ohci_ed ed; + struct usb_pipe pipe; + void *data; + int count; + struct ohci_td *tds; +}; +
/**************************************************************** * Root hub @@ -109,6 +117,56 @@ check_ohci_ports(struct usb_ohci_s *cntl) * Setup ****************************************************************/
+// Wait for next USB frame to start - for ensuring safe memory release. +static void +ohci_waittick(struct usb_ohci_s *cntl) +{ + barrier(); + struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + u32 startframe = hcca->frame_no; + u64 end = calc_future_tsc(1000 * 5); + for (;;) { + if (hcca->frame_no != startframe) + break; + if (check_tsc(end)) { + warn_timeout(); + return; + } + yield(); + } +} + +static void +ohci_free_pipes(struct usb_ohci_s *cntl) +{ + dprintf(7, "ohci_free_pipes %p\n", cntl); + + u32 creg = readl(&cntl->regs->control); + if (creg & (OHCI_CTRL_CLE|OHCI_CTRL_BLE)) { + writel(&cntl->regs->control, creg & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE)); + ohci_waittick(cntl); + } + + u32 *pos = &cntl->regs->ed_controlhead; + for (;;) { + struct ohci_ed *next = (void*)*pos; + if (!next) + break; + struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed); + if (pipe->pipe.cntl != &cntl->usb) { + *pos = next->hwNextED; + free(pipe); + } else { + pos = &next->hwNextED; + } + } + + writel(&cntl->regs->ed_controlcurrent, 0); + writel(&cntl->regs->ed_bulkcurrent, 0); + writel(&cntl->regs->control, creg); + cntl->usb.freelist = NULL; +} + static int start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca) { @@ -192,6 +250,7 @@ configure_ohci(void *data)
int count = check_ohci_ports(cntl); free_pipe(cntl->usb.defaultpipe); + ohci_free_pipes(cntl); if (! count) goto err; return; @@ -260,74 +319,13 @@ wait_ed(struct ohci_ed *ed) } }
-// Wait for next USB frame to start - for ensuring safe memory release. -static void -ohci_waittick(struct usb_ohci_s *cntl) -{ - barrier(); - struct ohci_hcca *hcca = (void*)cntl->regs->hcca; - u32 startframe = hcca->frame_no; - u64 end = calc_future_tsc(1000 * 5); - for (;;) { - if (hcca->frame_no != startframe) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } -} - -static void -signal_freelist(struct usb_ohci_s *cntl) -{ - u32 v = readl(&cntl->regs->control); - if (v & OHCI_CTRL_CLE) { - writel(&cntl->regs->control, v & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE)); - ohci_waittick(cntl); - writel(&cntl->regs->ed_controlcurrent, 0); - writel(&cntl->regs->ed_bulkcurrent, 0); - writel(&cntl->regs->control, v); - } else { - ohci_waittick(cntl); - } -} - -struct ohci_pipe { - struct ohci_ed ed; - struct usb_pipe pipe; - void *data; - int count; - struct ohci_td *tds; -}; - void -ohci_free_pipe(struct usb_pipe *p) +ohci_free_pipe(struct usb_pipe *pipe) { - if (! CONFIG_USB_OHCI) - return; - dprintf(7, "ohci_free_pipe %p\n", p); - struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); - struct usb_ohci_s *cntl = container_of( - pipe->pipe.cntl, struct usb_ohci_s, usb); - - u32 *pos = &cntl->regs->ed_controlhead; - for (;;) { - struct ohci_ed *next = (void*)*pos; - if (!next) { - // Not found?! Exit without freeing. - warn_internalerror(); - return; - } - if (next == &pipe->ed) { - *pos = next->hwNextED; - signal_freelist(cntl); - free(pipe); - return; - } - pos = &next->hwNextED; - } + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; }
struct usb_pipe * @@ -339,7 +337,17 @@ ohci_alloc_control_pipe(struct usb_pipe *dummy) dummy->cntl, struct usb_ohci_s, usb); dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb);
- // Allocate a queue head. + 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; + } + + // Allocate a new queue head. struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); if (!pipe) { warn_noalloc(); diff --git a/src/usb.h b/src/usb.h index 8b2af40..cc32eb7 100644 --- a/src/usb.h +++ b/src/usb.h @@ -6,7 +6,10 @@
// Information on a USB end point. struct usb_pipe { - struct usb_s *cntl; + union { + struct usb_s *cntl; + struct usb_pipe *freenext; + }; u64 path; u8 type; u8 ep; @@ -20,6 +23,7 @@ struct usb_pipe { // Common information for usb controllers. struct usb_s { struct usb_pipe *defaultpipe; + struct usb_pipe *freelist; struct mutex_s resetlock; struct pci_device *pci; int busid;
Instead of unregistering each control "endpoint descriptor" after it is used, keep them around for later users. Free all unused descriptors in one batch at the end of initialization. This should slightly optimize boot time, and it requires less overall interaction with the controller.
This also merges the code that allocates the control and bulk pipes, as they were quite similar before.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-uhci.c | 219 +++++++++++++++++++++++++++++--------------------------- 1 files changed, 114 insertions(+), 105 deletions(-)
diff --git a/src/usb-uhci.c b/src/usb-uhci.c index a78dbca..015b974 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -16,10 +16,19 @@ struct usb_uhci_s { struct usb_s usb; u16 iobase; - struct uhci_qh *control_qh, *bulk_qh; + struct uhci_qh *control_qh; struct uhci_framelist *framelist; };
+struct uhci_pipe { + struct uhci_qh qh; + struct uhci_td *next_td; + struct usb_pipe pipe; + u16 iobase; + u8 toggle; + u8 iscontrol; +}; +
/**************************************************************** * Root hub @@ -97,6 +106,52 @@ check_uhci_ports(struct usb_uhci_s *cntl) * Setup ****************************************************************/
+// Wait for next USB frame to start - for ensuring safe memory release. +static void +uhci_waittick(u16 iobase) +{ + barrier(); + u16 startframe = inw(iobase + USBFRNUM); + u64 end = calc_future_tsc(1000 * 5); + for (;;) { + if (inw(iobase + USBFRNUM) != startframe) + break; + if (check_tsc(end)) { + warn_timeout(); + return; + } + yield(); + } +} + +static void +uhci_free_pipes(struct usb_uhci_s *cntl) +{ + dprintf(7, "uhci_free_pipes %p\n", cntl); + + struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS); + for (;;) { + u32 link = pos->link; + if (link == UHCI_PTR_TERM) + break; + struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS); + struct uhci_pipe *pipe = container_of(next, struct uhci_pipe, qh); + if (pipe->pipe.cntl != &cntl->usb) + pos->link = next->link; + else + pos = next; + } + uhci_waittick(cntl->iobase); + for (;;) { + struct usb_pipe *usbpipe = cntl->usb.freelist; + if (!usbpipe) + break; + cntl->usb.freelist = usbpipe->freenext; + struct uhci_pipe *pipe = container_of(usbpipe, struct uhci_pipe, pipe); + free(pipe); + } +} + static void reset_uhci(struct usb_uhci_s *cntl, u16 bdf) { @@ -122,9 +177,9 @@ configure_uhci(void *data) // Allocate ram for schedule storage struct uhci_td *term_td = malloc_high(sizeof(*term_td)); struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); - struct uhci_qh *intr_qh = malloc_high(sizeof(*intr_qh)); - struct uhci_qh *term_qh = malloc_high(sizeof(*term_qh)); - if (!term_td || !fl || !intr_qh || !term_qh) { + struct uhci_pipe *intr_pipe = malloc_high(sizeof(*intr_pipe)); + struct uhci_pipe *term_pipe = malloc_high(sizeof(*term_pipe)); + if (!term_td || !fl || !intr_pipe || !term_pipe) { warn_noalloc(); goto fail; } @@ -134,19 +189,21 @@ configure_uhci(void *data) term_td->link = UHCI_PTR_TERM; term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN); - memset(term_qh, 0, sizeof(*term_qh)); - term_qh->element = (u32)term_td; - term_qh->link = UHCI_PTR_TERM; + memset(term_pipe, 0, sizeof(*term_pipe)); + term_pipe->qh.element = (u32)term_td; + term_pipe->qh.link = UHCI_PTR_TERM; + term_pipe->pipe.cntl = &cntl->usb;
// Set schedule to point to primary intr queue head - memset(intr_qh, 0, sizeof(*intr_qh)); - intr_qh->element = UHCI_PTR_TERM; - intr_qh->link = (u32)term_qh | UHCI_PTR_QH; + memset(intr_pipe, 0, sizeof(*intr_pipe)); + intr_pipe->qh.element = UHCI_PTR_TERM; + intr_pipe->qh.link = (u32)&term_pipe->qh | UHCI_PTR_QH; + intr_pipe->pipe.cntl = &cntl->usb; int i; for (i=0; i<ARRAY_SIZE(fl->links); i++) - fl->links[i] = (u32)intr_qh | UHCI_PTR_QH; + fl->links[i] = (u32)&intr_pipe->qh | UHCI_PTR_QH; cntl->framelist = fl; - cntl->control_qh = cntl->bulk_qh = intr_qh; + cntl->control_qh = &intr_pipe->qh; barrier();
// Set the frame length to the default: 1 ms exactly @@ -164,6 +221,7 @@ configure_uhci(void *data) // Find devices int count = check_uhci_ports(cntl); free_pipe(cntl->usb.defaultpipe); + uhci_free_pipes(cntl); if (count) // Success return; @@ -173,8 +231,8 @@ configure_uhci(void *data) fail: free(term_td); free(fl); - free(intr_qh); - free(term_qh); + free(intr_pipe); + free(term_pipe); free(cntl); }
@@ -212,32 +270,6 @@ uhci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
-struct uhci_pipe { - struct uhci_qh qh; - struct uhci_td *next_td; - struct usb_pipe pipe; - u16 iobase; - u8 toggle; -}; - -// Wait for next USB frame to start - for ensuring safe memory release. -static void -uhci_waittick(u16 iobase) -{ - barrier(); - u16 startframe = inw(iobase + USBFRNUM); - u64 end = calc_future_tsc(1000 * 5); - for (;;) { - if (inw(iobase + USBFRNUM) != startframe) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } -} - static int wait_pipe(struct uhci_pipe *pipe, int timeout) { @@ -263,49 +295,44 @@ wait_pipe(struct uhci_pipe *pipe, int timeout) }
void -uhci_free_pipe(struct usb_pipe *p) +uhci_free_pipe(struct usb_pipe *pipe) { if (! CONFIG_USB_UHCI) return; - dprintf(7, "uhci_free_pipe %p\n", p); - struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe); - struct usb_uhci_s *cntl = container_of( - pipe->pipe.cntl, struct usb_uhci_s, usb); - - struct uhci_qh *pos = (void*)(cntl->framelist->links[0] & ~UHCI_PTR_BITS); - for (;;) { - u32 link = pos->link; - if (link == UHCI_PTR_TERM) { - // Not found?! Exit without freeing. - warn_internalerror(); - return; - } - struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS); - if (next == &pipe->qh) { - pos->link = next->link; - if (cntl->control_qh == next) - cntl->control_qh = pos; - if (cntl->bulk_qh == next) - cntl->bulk_qh = pos; - uhci_waittick(cntl->iobase); - free(pipe); - return; - } - pos = next; - } + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; }
-struct usb_pipe * -uhci_alloc_control_pipe(struct usb_pipe *dummy) +static struct usb_pipe * +uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) { if (! CONFIG_USB_UHCI) return NULL; struct usb_uhci_s *cntl = container_of( dummy->cntl, struct usb_uhci_s, usb); - dprintf(7, "uhci_alloc_control_pipe %p\n", &cntl->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; + }
- // Allocate a queue head. - struct uhci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); + // Allocate a new queue head. + struct uhci_pipe *pipe; + if (iscontrol) + pipe = malloc_tmphigh(sizeof(*pipe)); + else + pipe = malloc_low(sizeof(*pipe)); if (!pipe) { warn_noalloc(); return NULL; @@ -314,17 +341,30 @@ uhci_alloc_control_pipe(struct usb_pipe *dummy) 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 (cntl->bulk_qh == control_qh) - cntl->bulk_qh = &pipe->qh; + if (iscontrol) + 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) @@ -382,35 +422,6 @@ uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize return ret; }
-struct usb_pipe * -uhci_alloc_bulk_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_bulk_pipe %p\n", &cntl->usb); - - // Allocate a queue head. - struct uhci_pipe *pipe = malloc_low(sizeof(*pipe)); - if (!pipe) { - warn_noalloc(); - return NULL; - } - memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); - pipe->qh.element = UHCI_PTR_TERM; - pipe->iobase = cntl->iobase; - - // Add queue head to controller list. - struct uhci_qh *bulk_qh = cntl->bulk_qh; - pipe->qh.link = bulk_qh->link; - barrier(); - bulk_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - - return &pipe->pipe; -} - static int wait_td(struct uhci_td *td) { @@ -547,8 +558,6 @@ uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp) intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; if (cntl->control_qh == intr_qh) cntl->control_qh = &pipe->qh; - if (cntl->bulk_qh == intr_qh) - cntl->bulk_qh = &pipe->qh; } else { int startpos = 1<<(frameexp-1); pipe->qh.link = fl->links[startpos];
Instead of unregistering each control "endpoint descriptor" after it is used, keep them around for later users. Free all unused descriptors in one batch at the end of initialization. This should slightly optimize boot time, and it requires less overall interaction with the controller.
This also merges the code that allocates the control and bulk pipes, as they were quite similar before.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 224 ++++++++++++++++++++++++++++++-------------------------- 1 files changed, 119 insertions(+), 105 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 9bdd638..2978072 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -26,6 +26,14 @@ struct usb_ehci_s { int legacycount; };
+struct ehci_pipe { + struct ehci_qh qh; + struct ehci_qtd *next_td, *tds; + void *data; + struct usb_pipe pipe; + u8 iscontrol; +}; +
/**************************************************************** * Root hub @@ -169,6 +177,76 @@ check_ehci_ports(struct usb_ehci_s *cntl) * Setup ****************************************************************/
+// Wait for next USB async frame to start - for ensuring safe memory release. +static void +ehci_waittick(struct usb_ehci_s *cntl) +{ + if (MODE16) { + msleep(10); + return; + } + // Wait for access to "doorbell" + barrier(); + u32 cmd, sts; + u64 end = calc_future_tsc(100); + for (;;) { + sts = readl(&cntl->regs->usbsts); + if (!(sts & STS_IAA)) { + cmd = readl(&cntl->regs->usbcmd); + if (!(cmd & CMD_IAAD)) + break; + } + if (check_tsc(end)) { + warn_timeout(); + return; + } + yield(); + } + // Ring "doorbell" + writel(&cntl->regs->usbcmd, cmd | CMD_IAAD); + // Wait for completion + for (;;) { + sts = readl(&cntl->regs->usbsts); + if (sts & STS_IAA) + break; + if (check_tsc(end)) { + warn_timeout(); + return; + } + yield(); + } + // Ack completion + writel(&cntl->regs->usbsts, STS_IAA); +} + +static void +ehci_free_pipes(struct usb_ehci_s *cntl) +{ + dprintf(7, "ehci_free_pipes %p\n", cntl); + + struct ehci_qh *start = cntl->async_qh; + struct ehci_qh *pos = start; + for (;;) { + struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS); + if (next == start) + break; + struct ehci_pipe *pipe = container_of(next, struct ehci_pipe, qh); + if (pipe->pipe.cntl != &cntl->usb) + pos->next = next->next; + else + pos = next; + } + ehci_waittick(cntl); + for (;;) { + struct usb_pipe *usbpipe = cntl->usb.freelist; + if (!usbpipe) + break; + cntl->usb.freelist = usbpipe->freenext; + struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); + free(pipe); + } +} + static void configure_ehci(void *data) { @@ -233,6 +311,7 @@ configure_ehci(void *data) // Find devices int count = check_ehci_ports(cntl); free_pipe(cntl->usb.defaultpipe); + ehci_free_pipes(cntl); if (count) // Success return; @@ -303,55 +382,6 @@ ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) * End point communication ****************************************************************/
-struct ehci_pipe { - struct ehci_qh qh; - struct ehci_qtd *next_td, *tds; - void *data; - struct usb_pipe pipe; -}; - -// Wait for next USB async frame to start - for ensuring safe memory release. -static void -ehci_waittick(struct usb_ehci_s *cntl) -{ - if (MODE16) { - msleep(10); - return; - } - // Wait for access to "doorbell" - barrier(); - u32 cmd, sts; - u64 end = calc_future_tsc(100); - for (;;) { - sts = readl(&cntl->regs->usbsts); - if (!(sts & STS_IAA)) { - cmd = readl(&cntl->regs->usbcmd); - if (!(cmd & CMD_IAAD)) - break; - } - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } - // Ring "doorbell" - writel(&cntl->regs->usbcmd, cmd | CMD_IAAD); - // Wait for completion - for (;;) { - sts = readl(&cntl->regs->usbsts); - if (sts & STS_IAA) - break; - if (check_tsc(end)) { - warn_timeout(); - return; - } - yield(); - } - // Ack completion - writel(&cntl->regs->usbsts, STS_IAA); -} - static void ehci_reset_pipe(struct ehci_pipe *pipe) { @@ -394,45 +424,44 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) }
void -ehci_free_pipe(struct usb_pipe *p) +ehci_free_pipe(struct usb_pipe *pipe) { if (! CONFIG_USB_EHCI) return; - dprintf(7, "ehci_free_pipe %p\n", p); - struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); - struct usb_ehci_s *cntl = container_of( - pipe->pipe.cntl, struct usb_ehci_s, usb); - - struct ehci_qh *start = cntl->async_qh; - struct ehci_qh *pos = start; - for (;;) { - struct ehci_qh *next = (void*)(pos->next & ~EHCI_PTR_BITS); - if (next == start) { - // Not found?! Exit without freeing. - warn_internalerror(); - return; - } - if (next == &pipe->qh) { - pos->next = next->next; - ehci_waittick(cntl); - free(pipe); - return; - } - pos = next; - } + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; }
-struct usb_pipe * -ehci_alloc_control_pipe(struct usb_pipe *dummy) +static struct usb_pipe * +ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) { if (! CONFIG_USB_EHCI) return NULL; struct usb_ehci_s *cntl = container_of( dummy->cntl, struct usb_ehci_s, usb); - dprintf(7, "ehci_alloc_control_pipe %p\n", &cntl->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; + }
- // Allocate a queue head. - struct ehci_pipe *pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); + // Allocate a new queue head. + struct ehci_pipe *pipe; + if (iscontrol) + pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); + else + pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); if (!pipe) { warn_noalloc(); return NULL; @@ -440,6 +469,7 @@ ehci_alloc_control_pipe(struct usb_pipe *dummy) 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; @@ -449,6 +479,18 @@ ehci_alloc_control_pipe(struct usb_pipe *dummy) 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) { @@ -546,34 +588,6 @@ ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize return ret; }
-struct usb_pipe * -ehci_alloc_bulk_pipe(struct usb_pipe *dummy) -{ - // XXX - this func is same as alloc_control except for malloc_low - if (! CONFIG_USB_EHCI) - return NULL; - struct usb_ehci_s *cntl = container_of( - dummy->cntl, struct usb_ehci_s, usb); - dprintf(7, "ehci_alloc_bulk_pipe %p\n", &cntl->usb); - - // Allocate a queue head. - struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); - if (!pipe) { - warn_noalloc(); - return NULL; - } - memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); - pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; - - // Add queue head to controller list. - struct ehci_qh *async_qh = cntl->async_qh; - pipe->qh.next = async_qh->next; - barrier(); - async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; - return &pipe->pipe; -} - #define STACKQTDS 4
int
Now that all controllers use a free list, maintain the free list in the common code.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 11 ----------- src/usb-ehci.h | 1 - src/usb-ohci.c | 9 --------- src/usb-ohci.h | 1 - src/usb-uhci.c | 11 ----------- src/usb-uhci.h | 1 - src/usb.c | 13 ++++--------- 7 files changed, 4 insertions(+), 43 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 2978072..5717dc6 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -423,17 +423,6 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) return 0; }
-void -ehci_free_pipe(struct usb_pipe *pipe) -{ - if (! CONFIG_USB_EHCI) - return; - // Add to controller's free list. - struct usb_s *cntl = pipe->cntl; - pipe->freenext = cntl->freelist; - cntl->freelist = pipe; -} - static struct usb_pipe * ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) { diff --git a/src/usb-ehci.h b/src/usb-ehci.h index 1a2c6c7..fd38b73 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -4,7 +4,6 @@ // usb-ehci.c int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci); struct usb_pipe; -void ehci_free_pipe(struct usb_pipe *p); struct usb_pipe *ehci_alloc_control_pipe(struct usb_pipe *dummy); int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 7a437ad..ac1eb37 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -319,15 +319,6 @@ wait_ed(struct ohci_ed *ed) } }
-void -ohci_free_pipe(struct usb_pipe *pipe) -{ - // Add to controller's free list. - struct usb_s *cntl = pipe->cntl; - pipe->freenext = cntl->freelist; - cntl->freelist = pipe; -} - struct usb_pipe * ohci_alloc_control_pipe(struct usb_pipe *dummy) { diff --git a/src/usb-ohci.h b/src/usb-ohci.h index c7670ff..6162d32 100644 --- a/src/usb-ohci.h +++ b/src/usb-ohci.h @@ -4,7 +4,6 @@ // usb-ohci.c void ohci_init(struct pci_device *pci, int busid); struct usb_pipe; -void ohci_free_pipe(struct usb_pipe *p); struct usb_pipe *ohci_alloc_control_pipe(struct usb_pipe *dummy); int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 015b974..4f7fbb4 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -294,17 +294,6 @@ wait_pipe(struct uhci_pipe *pipe, int timeout) } }
-void -uhci_free_pipe(struct usb_pipe *pipe) -{ - if (! CONFIG_USB_UHCI) - return; - // Add to controller's free list. - struct usb_s *cntl = pipe->cntl; - pipe->freenext = cntl->freelist; - cntl->freelist = pipe; -} - static struct usb_pipe * uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) { diff --git a/src/usb-uhci.h b/src/usb-uhci.h index b5f70f7..59b190d 100644 --- a/src/usb-uhci.h +++ b/src/usb-uhci.h @@ -4,7 +4,6 @@ // usb-uhci.c void uhci_init(struct pci_device *pci, int busid); struct usb_pipe; -void uhci_free_pipe(struct usb_pipe *p); struct usb_pipe *uhci_alloc_control_pipe(struct usb_pipe *dummy); int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); diff --git a/src/usb.c b/src/usb.c index 1f69d16..f522e1a 100644 --- a/src/usb.c +++ b/src/usb.c @@ -30,15 +30,10 @@ free_pipe(struct usb_pipe *pipe) ASSERT32FLAT(); if (!pipe) return; - switch (pipe->type) { - default: - case USB_TYPE_UHCI: - return uhci_free_pipe(pipe); - case USB_TYPE_OHCI: - return ohci_free_pipe(pipe); - case USB_TYPE_EHCI: - return ehci_free_pipe(pipe); - } + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; }
// Allocate a control pipe to a default endpoint (which can only be
Now that all pipes use a free list, there is no need to cache the controller's default pipe. The regular free list provides the same capability.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 1 - src/usb-ohci.c | 1 - src/usb-uhci.c | 1 - src/usb.c | 37 +++++++++++++++++-------------------- src/usb.h | 1 - 5 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 5717dc6..0678560 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -310,7 +310,6 @@ configure_ehci(void *data)
// Find devices int count = check_ehci_ports(cntl); - free_pipe(cntl->usb.defaultpipe); ehci_free_pipes(cntl); if (count) // Success diff --git a/src/usb-ohci.c b/src/usb-ohci.c index ac1eb37..d77727e 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -249,7 +249,6 @@ configure_ohci(void *data) goto err;
int count = check_ohci_ports(cntl); - free_pipe(cntl->usb.defaultpipe); ohci_free_pipes(cntl); if (! count) goto err; diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 4f7fbb4..9d46762 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -220,7 +220,6 @@ configure_uhci(void *data)
// Find devices int count = check_uhci_ports(cntl); - free_pipe(cntl->usb.defaultpipe); uhci_free_pipes(cntl); if (count) // Success diff --git a/src/usb.c b/src/usb.c index f522e1a..e7ee6bc 100644 --- a/src/usb.c +++ b/src/usb.c @@ -246,19 +246,16 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) if (cntl->maxaddr >= USB_MAXADDR) return NULL;
- struct usb_pipe *defpipe = cntl->defaultpipe; - if (!defpipe) { - // Create a pipe for the default address. - struct usb_pipe dummy; - memset(&dummy, 0, sizeof(dummy)); - dummy.cntl = cntl; - dummy.type = cntl->type; - dummy.maxpacket = 8; - dummy.path = (u64)-1; - cntl->defaultpipe = defpipe = alloc_default_control_pipe(&dummy); - if (!defpipe) - return NULL; - } + // Create a pipe for the default address. + struct usb_pipe dummy; + memset(&dummy, 0, sizeof(dummy)); + dummy.cntl = cntl; + dummy.type = cntl->type; + dummy.maxpacket = 8; + dummy.path = (u64)-1; + struct usb_pipe *defpipe = alloc_default_control_pipe(&dummy); + if (!defpipe) + return NULL; defpipe->speed = speed; if (hub->pipe) { if (hub->pipe->speed == USB_HIGHSPEED) { @@ -271,6 +268,9 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) } else { defpipe->tt_devaddr = defpipe->tt_port = 0; } + if (hub->pipe) + defpipe->path = hub->pipe->path; + defpipe->path = (defpipe->path << 8) | port;
msleep(USB_TIME_RSTRCY);
@@ -281,19 +281,16 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) req.wIndex = 0; req.wLength = 0; int ret = send_default_control(defpipe, &req, NULL); - if (ret) + if (ret) { + free_pipe(defpipe); return NULL; + }
msleep(USB_TIME_SETADDR_RECOVERY);
cntl->maxaddr++; defpipe->devaddr = cntl->maxaddr; - struct usb_pipe *pipe = alloc_default_control_pipe(defpipe); - defpipe->devaddr = 0; - if (hub->pipe) - pipe->path = hub->pipe->path; - pipe->path = (pipe->path << 8) | port; - return pipe; + return defpipe; }
// Called for every found device - see if a driver is available for diff --git a/src/usb.h b/src/usb.h index cc32eb7..47b25b6 100644 --- a/src/usb.h +++ b/src/usb.h @@ -22,7 +22,6 @@ struct usb_pipe {
// Common information for usb controllers. struct usb_s { - struct usb_pipe *defaultpipe; struct usb_pipe *freelist; struct mutex_s resetlock; struct pci_device *pci;
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@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.
Create the usbdevice_s struct and use it during the enumeration processes.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb.c | 49 +++++++++++++++++++++++++++++++------------------ src/usb.h | 8 ++++++++ 2 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/src/usb.c b/src/usb.c index 7c49c6a..81aa429 100644 --- a/src/usb.c +++ b/src/usb.c @@ -245,14 +245,15 @@ set_configuration(struct usb_pipe *pipe, u16 val)
// Assign an address to a device in the default state on the given // controller. -static struct usb_pipe * -usb_set_address(struct usbhub_s *hub, int port, int speed) +static int +usb_set_address(struct usbdevice_s *usbdev) { ASSERT32FLAT(); + struct usbhub_s *hub = usbdev->hub; struct usb_s *cntl = hub->cntl; dprintf(3, "set_address %p\n", cntl); if (cntl->maxaddr >= USB_MAXADDR) - return NULL; + return -1;
// Create a pipe for the default address. struct usb_pipe dummy; @@ -264,12 +265,13 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) dummy.eptype = USB_ENDPOINT_XFER_CONTROL; struct usb_pipe *defpipe = alloc_async_pipe(&dummy); if (!defpipe) - return NULL; - defpipe->speed = speed; + return -1; + usbdev->defpipe = defpipe; + defpipe->speed = usbdev->speed; if (hub->pipe) { if (hub->pipe->speed == USB_HIGHSPEED) { defpipe->tt_devaddr = hub->pipe->devaddr; - defpipe->tt_port = port; + defpipe->tt_port = usbdev->port; } else { defpipe->tt_devaddr = hub->pipe->tt_devaddr; defpipe->tt_port = hub->pipe->tt_port; @@ -279,7 +281,7 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) } if (hub->pipe) defpipe->path = hub->pipe->path; - defpipe->path = (defpipe->path << 8) | port; + defpipe->path = (defpipe->path << 8) | usbdev->port;
msleep(USB_TIME_RSTRCY);
@@ -292,22 +294,23 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) int ret = send_default_control(defpipe, &req, NULL); if (ret) { free_pipe(defpipe); - return NULL; + return -1; }
msleep(USB_TIME_SETADDR_RECOVERY);
cntl->maxaddr++; defpipe->devaddr = cntl->maxaddr; - return defpipe; + return 0; }
// Called for every found device - see if a driver is available for // this device and do setup if so. static int -configure_usb_device(struct usb_pipe *pipe) +configure_usb_device(struct usbdevice_s *usbdev) { ASSERT32FLAT(); + struct usb_pipe *pipe = usbdev->defpipe; dprintf(3, "config_usb: %p\n", pipe);
// Set the max packet size for endpoint 0 of this device. @@ -362,8 +365,9 @@ fail: static void usb_init_hub_port(void *data) { - struct usbhub_s *hub = data; - u32 port = hub->port; // XXX - find better way to pass port + struct usbdevice_s *usbdev = data; + struct usbhub_s *hub = usbdev->hub; + u32 port = usbdev->port;
// Detect if device present (and possibly start reset) int ret = hub->op->detect(hub, port); @@ -377,23 +381,25 @@ usb_init_hub_port(void *data) if (ret < 0) // Reset failed goto resetfail; + usbdev->speed = ret;
// Set address of port - struct usb_pipe *pipe = usb_set_address(hub, port, ret); - if (!pipe) { + ret = usb_set_address(usbdev); + if (ret) { hub->op->disconnect(hub, port); goto resetfail; } mutex_unlock(&hub->cntl->resetlock);
// Configure the device - int count = configure_usb_device(pipe); - free_pipe(pipe); + int count = configure_usb_device(usbdev); + free_pipe(usbdev->defpipe); if (!count) hub->op->disconnect(hub, port); hub->devcount += count; done: hub->threads--; + free(usbdev); return;
resetfail: @@ -410,8 +416,15 @@ usb_enumerate(struct usbhub_s *hub) // Launch a thread for every port. int i; for (i=0; i<portcount; i++) { - hub->port = i; - run_thread(usb_init_hub_port, hub); + struct usbdevice_s *usbdev = malloc_tmphigh(sizeof(*usbdev)); + if (!usbdev) { + warn_noalloc(); + continue; + } + memset(usbdev, 0, sizeof(*usbdev)); + usbdev->hub = hub; + usbdev->port = i; + run_thread(usb_init_hub_port, usbdev); }
// Wait for threads to complete. diff --git a/src/usb.h b/src/usb.h index 44f8a96..ab7f559 100644 --- a/src/usb.h +++ b/src/usb.h @@ -21,6 +21,14 @@ struct usb_pipe { u8 eptype; };
+// Common information for usb devices. +struct usbdevice_s { + struct usbhub_s *hub; + struct usb_pipe *defpipe; + u32 port; + u8 speed; +}; + // Common information for usb controllers. struct usb_s { struct usb_pipe *freelist;
Pass the usbdevice_s info to device configuration and allocation code.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-hid.c | 28 +++++++++++++++------------- src/usb-hid.h | 6 ++---- src/usb-hub.c | 8 ++++---- src/usb-hub.h | 4 ++-- src/usb-msc.c | 15 ++++++++------- src/usb-msc.h | 6 ++---- src/usb.c | 35 +++++++++++++++++++---------------- src/usb.h | 13 +++++++------ 8 files changed, 59 insertions(+), 56 deletions(-)
diff --git a/src/usb-hid.c b/src/usb-hid.c index 168b7fa..21363c3 100644 --- a/src/usb-hid.c +++ b/src/usb-hid.c @@ -49,7 +49,8 @@ set_idle(struct usb_pipe *pipe, int ms) #define KEYREPEATMS 33
static int -usb_kbd_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) +usb_kbd_init(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_KEYBOARD) return -1; @@ -61,15 +62,15 @@ usb_kbd_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) return -1;
// Enable "boot" protocol. - int ret = set_protocol(pipe, 0); + int ret = set_protocol(usbdev->defpipe, 0); if (ret) return -1; // Periodically send reports to enable key repeat. - ret = set_idle(pipe, KEYREPEATMS); + ret = set_idle(usbdev->defpipe, KEYREPEATMS); if (ret) return -1;
- keyboard_pipe = alloc_intr_pipe(pipe, epdesc); + keyboard_pipe = alloc_intr_pipe(usbdev, epdesc); if (!keyboard_pipe) return -1;
@@ -78,7 +79,8 @@ usb_kbd_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) }
static int -usb_mouse_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) +usb_mouse_init(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_MOUSE) return -1; @@ -90,11 +92,11 @@ usb_mouse_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) return -1;
// Enable "boot" protocol. - int ret = set_protocol(pipe, 0); + int ret = set_protocol(usbdev->defpipe, 0); if (ret) return -1;
- mouse_pipe = alloc_intr_pipe(pipe, epdesc); + mouse_pipe = alloc_intr_pipe(usbdev, epdesc); if (!mouse_pipe) return -1;
@@ -104,29 +106,29 @@ usb_mouse_init(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc)
// Initialize a found USB HID device (if applicable). int -usb_hid_init(struct usb_pipe *pipe - , struct usb_interface_descriptor *iface, int imax) +usb_hid_init(struct usbdevice_s *usbdev) { if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE) return -1; - dprintf(2, "usb_hid_init %p\n", pipe); + dprintf(2, "usb_hid_init %p\n", usbdev->defpipe);
+ struct usb_interface_descriptor *iface = usbdev->iface; if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT) // Doesn't support boot protocol. return -1;
// Find intr in endpoint. struct usb_endpoint_descriptor *epdesc = findEndPointDesc( - iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN); + usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN); if (!epdesc) { dprintf(1, "No usb hid intr in?\n"); return -1; }
if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD) - return usb_kbd_init(pipe, epdesc); + return usb_kbd_init(usbdev, epdesc); if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) - return usb_mouse_init(pipe, epdesc); + return usb_mouse_init(usbdev, epdesc); return -1; }
diff --git a/src/usb-hid.h b/src/usb-hid.h index 7fbcf4b..bd6445c 100644 --- a/src/usb-hid.h +++ b/src/usb-hid.h @@ -2,10 +2,8 @@ #define __USB_HID_H
// usb-hid.c -struct usb_interface_descriptor; -struct usb_pipe; -int usb_hid_init(struct usb_pipe *pipe - , struct usb_interface_descriptor *iface, int imax); +struct usbdevice_s; +int usb_hid_init(struct usbdevice_s *usbdev); inline int usb_kbd_active(void); inline int usb_kbd_command(int command, u8 *param); inline int usb_mouse_active(void); diff --git a/src/usb-hub.c b/src/usb-hub.c index b2d9ff2..caa6a3b 100644 --- a/src/usb-hub.c +++ b/src/usb-hub.c @@ -158,21 +158,21 @@ static struct usbhub_op_s HubOp = {
// Configure a usb hub and then find devices connected to it. int -usb_hub_init(struct usb_pipe *pipe) +usb_hub_init(struct usbdevice_s *usbdev) { ASSERT32FLAT(); if (!CONFIG_USB_HUB) return -1;
struct usb_hub_descriptor desc; - int ret = get_hub_desc(pipe, &desc); + int ret = get_hub_desc(usbdev->defpipe, &desc); if (ret) return ret;
struct usbhub_s hub; memset(&hub, 0, sizeof(hub)); - hub.pipe = pipe; - hub.cntl = pipe->cntl; + hub.pipe = usbdev->defpipe; + hub.cntl = usbdev->defpipe->cntl; hub.powerwait = desc.bPwrOn2PwrGood * 2; hub.portcount = desc.bNbrPorts; hub.op = &HubOp; diff --git a/src/usb-hub.h b/src/usb-hub.h index 7672028..a75cbda 100644 --- a/src/usb-hub.h +++ b/src/usb-hub.h @@ -2,8 +2,8 @@ #define __USB_HUB_H
// usb-hub.c -struct usb_pipe; -int usb_hub_init(struct usb_pipe *pipe); +struct usbdevice_s; +int usb_hub_init(struct usbdevice_s *usbdev);
/**************************************************************** diff --git a/src/usb-msc.c b/src/usb-msc.c index e143401..dad90d6 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -124,13 +124,13 @@ fail:
// Configure a usb msc device. int -usb_msc_init(struct usb_pipe *pipe - , struct usb_interface_descriptor *iface, int imax) +usb_msc_init(struct usbdevice_s *usbdev) { if (!CONFIG_USB_MSC) return -1;
// Verify right kind of device + struct usb_interface_descriptor *iface = usbdev->iface; if ((iface->bInterfaceSubClass != US_SC_SCSI && iface->bInterfaceSubClass != US_SC_ATAPI_8070 && iface->bInterfaceSubClass != US_SC_ATAPI_8020) @@ -151,17 +151,18 @@ usb_msc_init(struct usb_pipe *pipe
// Find bulk in and bulk out endpoints. struct usb_endpoint_descriptor *indesc = findEndPointDesc( - iface, imax, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); + usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); struct usb_endpoint_descriptor *outdesc = findEndPointDesc( - iface, imax, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); + usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); if (!indesc || !outdesc) goto fail; - udrive_g->bulkin = alloc_bulk_pipe(pipe, indesc); - udrive_g->bulkout = alloc_bulk_pipe(pipe, outdesc); + udrive_g->bulkin = alloc_bulk_pipe(usbdev, indesc); + udrive_g->bulkout = alloc_bulk_pipe(usbdev, outdesc); if (!udrive_g->bulkin || !udrive_g->bulkout) goto fail;
- int prio = bootprio_find_usb(pipe->cntl->pci, pipe->path); + int prio = bootprio_find_usb(usbdev->defpipe->cntl->pci + , usbdev->defpipe->path); int ret = scsi_init_drive(&udrive_g->drive, "USB MSC", prio); if (ret) goto fail; diff --git a/src/usb-msc.h b/src/usb-msc.h index 12d749c..31c81b9 100644 --- a/src/usb-msc.h +++ b/src/usb-msc.h @@ -4,10 +4,8 @@ // usb-msc.c struct disk_op_s; int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize); -struct usb_interface_descriptor; -struct usb_pipe; -int usb_msc_init(struct usb_pipe *pipe - , struct usb_interface_descriptor *iface, int imax); +struct usbdevice_s; +int usb_msc_init(struct usbdevice_s *usbdev);
/**************************************************************** diff --git a/src/usb.c b/src/usb.c index 81aa429..1657bf5 100644 --- a/src/usb.c +++ b/src/usb.c @@ -86,19 +86,20 @@ send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize
// Fill "pipe" endpoint info from an endpoint descriptor. static void -desc2pipe(struct usb_pipe *newpipe, struct usb_pipe *origpipe +desc2pipe(struct usb_pipe *newpipe, struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { - memcpy(newpipe, origpipe, sizeof(*newpipe)); + memcpy(newpipe, usbdev->defpipe, sizeof(*newpipe)); newpipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; newpipe->maxpacket = epdesc->wMaxPacketSize; }
struct usb_pipe * -alloc_bulk_pipe(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) +alloc_bulk_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { struct usb_pipe dummy; - desc2pipe(&dummy, pipe, epdesc); + desc2pipe(&dummy, usbdev, epdesc); dummy.eptype = USB_ENDPOINT_XFER_BULK; return alloc_async_pipe(&dummy); } @@ -118,18 +119,19 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) }
struct usb_pipe * -alloc_intr_pipe(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) +alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { struct usb_pipe dummy; - desc2pipe(&dummy, pipe, epdesc); + desc2pipe(&dummy, usbdev, epdesc); // Find the exponential period of the requested time. int period = epdesc->bInterval; int frameexp; - if (pipe->speed != USB_HIGHSPEED) + if (usbdev->speed != USB_HIGHSPEED) frameexp = (period <= 0) ? 0 : __fls(period); else frameexp = (period <= 4) ? 0 : period - 4; - switch (pipe->type) { + switch (dummy.type) { default: case USB_TYPE_UHCI: return uhci_alloc_intr_pipe(&dummy, frameexp); @@ -161,12 +163,11 @@ usb_poll_intr(struct usb_pipe *pipe_fl, void *data)
// Find the first endpoing of a given type in an interface description. struct usb_endpoint_descriptor * -findEndPointDesc(struct usb_interface_descriptor *iface, int imax - , int type, int dir) +findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir) { - struct usb_endpoint_descriptor *epdesc = (void*)&iface[1]; + struct usb_endpoint_descriptor *epdesc = (void*)&usbdev->iface[1]; for (;;) { - if ((void*)epdesc >= (void*)iface + imax + if ((void*)epdesc >= (void*)usbdev->iface + usbdev->imax || epdesc->bDescriptorType == USB_DT_INTERFACE) { return NULL; } @@ -345,13 +346,15 @@ configure_usb_device(struct usbdevice_s *usbdev) goto fail;
// Configure driver. - int imax = (void*)config + config->wTotalLength - (void*)iface; + usbdev->config = config; + usbdev->iface = iface; + usbdev->imax = (void*)config + config->wTotalLength - (void*)iface; if (iface->bInterfaceClass == USB_CLASS_HUB) - ret = usb_hub_init(pipe); + ret = usb_hub_init(usbdev); else if (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE) - ret = usb_msc_init(pipe, iface, imax); + ret = usb_msc_init(usbdev); else - ret = usb_hid_init(pipe, iface, imax); + ret = usb_hid_init(usbdev); if (ret) goto fail;
diff --git a/src/usb.h b/src/usb.h index ab7f559..83ccb58 100644 --- a/src/usb.h +++ b/src/usb.h @@ -26,6 +26,9 @@ struct usbdevice_s { struct usbhub_s *hub; struct usb_pipe *defpipe; u32 port; + struct usb_config_descriptor *config; + struct usb_interface_descriptor *iface; + int imax; u8 speed; };
@@ -215,14 +218,12 @@ int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *re , void *data); int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); void free_pipe(struct usb_pipe *pipe); -struct usb_pipe *alloc_bulk_pipe(struct usb_pipe *pipe +struct usb_pipe *alloc_bulk_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe *alloc_intr_pipe(struct usb_pipe *pipe +struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); int usb_poll_intr(struct usb_pipe *pipe, void *data); -struct usb_endpoint_descriptor *findEndPointDesc( - struct usb_interface_descriptor *iface, int imax, int type, int dir); -u32 mkendpFromDesc(struct usb_pipe *pipe - , struct usb_endpoint_descriptor *epdesc); +struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev + , int type, int dir);
#endif // usb.h
Instead of building a dummy u64 with the path, construct the path via the 'struct usbdevice_s' links.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/boot.c | 25 ++++++++++++++++--------- src/boot.h | 3 ++- src/usb-hub.c | 8 ++++---- src/usb-msc.c | 3 +-- src/usb.c | 14 +++++--------- src/usb.h | 3 +-- 6 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/src/boot.c b/src/boot.c index c737ba4..8cc94b0 100644 --- a/src/boot.c +++ b/src/boot.c @@ -14,6 +14,7 @@ #include "cmos.h" // inb_cmos #include "paravirt.h" // romfile_loadfile #include "pci.h" //pci_bdf_to_* +#include "usb.h" // struct usbdevice_s
/**************************************************************** @@ -194,20 +195,26 @@ int bootprio_find_named_rom(const char *name, int instance) return find_prio(desc); }
-int bootprio_find_usb(struct pci_device *pci, u64 path) +static char * +build_usb_path(char *buf, int max, struct usbhub_s *hub) +{ + if (!hub->usbdev) + // Root hub - nothing to add. + return buf; + char *p = build_usb_path(buf, max, hub->usbdev->hub); + p += snprintf(p, buf+max-p, "/hub@%x", hub->usbdev->port+1); + return p; +} + +int bootprio_find_usb(struct usbdevice_s *usbdev) { if (!CONFIG_BOOTORDER) return -1; // Find usb - for example: /pci@i0cf8/usb@1,2/hub@1/network@0/ethernet@0 - int i; char desc[256], *p; - p = build_pci_path(desc, sizeof(desc), "usb", pci); - for (i=56; i>0; i-=8) { - int port = (path >> i) & 0xff; - if (port != 0xff) - p += snprintf(p, desc+sizeof(desc)-p, "/hub@%x", port+1); - } - snprintf(p, desc+sizeof(desc)-p, "/*@%x", (u32)(path & 0xff)+1); + 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); return find_prio(desc); }
diff --git a/src/boot.h b/src/boot.h index 686f04d..c7c34dc 100644 --- a/src/boot.h +++ b/src/boot.h @@ -19,6 +19,7 @@ int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave); 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); -int bootprio_find_usb(struct pci_device *pci, u64 path); +struct usbdevice_s; +int bootprio_find_usb(struct usbdevice_s *usbdev);
#endif // __BOOT_H diff --git a/src/usb-hub.c b/src/usb-hub.c index caa6a3b..6f1aaa1 100644 --- a/src/usb-hub.c +++ b/src/usb-hub.c @@ -31,7 +31,7 @@ set_port_feature(struct usbhub_s *hub, int port, int feature) req.wIndex = port + 1; req.wLength = 0; mutex_lock(&hub->lock); - int ret = send_default_control(hub->pipe, &req, NULL); + int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); mutex_unlock(&hub->lock); return ret; } @@ -46,7 +46,7 @@ clear_port_feature(struct usbhub_s *hub, int port, int feature) req.wIndex = port + 1; req.wLength = 0; mutex_lock(&hub->lock); - int ret = send_default_control(hub->pipe, &req, NULL); + int ret = send_default_control(hub->usbdev->defpipe, &req, NULL); mutex_unlock(&hub->lock); return ret; } @@ -61,7 +61,7 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts) req.wIndex = port + 1; req.wLength = sizeof(*sts); mutex_lock(&hub->lock); - int ret = send_default_control(hub->pipe, &req, sts); + int ret = send_default_control(hub->usbdev->defpipe, &req, sts); mutex_unlock(&hub->lock); return ret; } @@ -171,7 +171,7 @@ usb_hub_init(struct usbdevice_s *usbdev)
struct usbhub_s hub; memset(&hub, 0, sizeof(hub)); - hub.pipe = usbdev->defpipe; + hub.usbdev = usbdev; hub.cntl = usbdev->defpipe->cntl; hub.powerwait = desc.bPwrOn2PwrGood * 2; hub.portcount = desc.bNbrPorts; diff --git a/src/usb-msc.c b/src/usb-msc.c index dad90d6..c21433f 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -161,8 +161,7 @@ usb_msc_init(struct usbdevice_s *usbdev) if (!udrive_g->bulkin || !udrive_g->bulkout) goto fail;
- int prio = bootprio_find_usb(usbdev->defpipe->cntl->pci - , usbdev->defpipe->path); + int prio = bootprio_find_usb(usbdev); int ret = scsi_init_drive(&udrive_g->drive, "USB MSC", prio); if (ret) goto fail; diff --git a/src/usb.c b/src/usb.c index 1657bf5..3eaa289 100644 --- a/src/usb.c +++ b/src/usb.c @@ -262,27 +262,23 @@ usb_set_address(struct usbdevice_s *usbdev) dummy.cntl = cntl; dummy.type = cntl->type; dummy.maxpacket = 8; - dummy.path = (u64)-1; dummy.eptype = USB_ENDPOINT_XFER_CONTROL; struct usb_pipe *defpipe = alloc_async_pipe(&dummy); if (!defpipe) return -1; usbdev->defpipe = defpipe; defpipe->speed = usbdev->speed; - if (hub->pipe) { - if (hub->pipe->speed == USB_HIGHSPEED) { - defpipe->tt_devaddr = hub->pipe->devaddr; + if (hub->usbdev) { + if (hub->usbdev->defpipe->speed == USB_HIGHSPEED) { + defpipe->tt_devaddr = hub->usbdev->defpipe->devaddr; defpipe->tt_port = usbdev->port; } else { - defpipe->tt_devaddr = hub->pipe->tt_devaddr; - defpipe->tt_port = hub->pipe->tt_port; + defpipe->tt_devaddr = hub->usbdev->defpipe->tt_devaddr; + defpipe->tt_port = hub->usbdev->defpipe->tt_port; } } else { defpipe->tt_devaddr = defpipe->tt_port = 0; } - if (hub->pipe) - defpipe->path = hub->pipe->path; - defpipe->path = (defpipe->path << 8) | usbdev->port;
msleep(USB_TIME_RSTRCY);
diff --git a/src/usb.h b/src/usb.h index 83ccb58..90b727a 100644 --- a/src/usb.h +++ b/src/usb.h @@ -10,7 +10,6 @@ struct usb_pipe { struct usb_s *cntl; struct usb_pipe *freenext; }; - u64 path; u8 type; u8 ep; u8 devaddr; @@ -45,7 +44,7 @@ struct usb_s { // Information for enumerating USB hubs struct usbhub_s { struct usbhub_op_s *op; - struct usb_pipe *pipe; + struct usbdevice_s *usbdev; struct usb_s *cntl; struct mutex_s lock; u32 powerwait;
Build the control pipe information in alloc_async_pipe directly from the usbdevice and usb_endpoint_descriptor information. This simplifies the callers as they now only need to allocate/free the devices, and do not need to peek into the pipe structure.
Replace alloc_bulk_pipe with alloc_async_pipe as they both perform the same action now.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-msc.c | 4 +- src/usb.c | 131 +++++++++++++++++++++++++++++--------------------------- src/usb.h | 5 +- 3 files changed, 73 insertions(+), 67 deletions(-)
diff --git a/src/usb-msc.c b/src/usb-msc.c index c21433f..4bf24a3 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -156,8 +156,8 @@ usb_msc_init(struct usbdevice_s *usbdev) usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); if (!indesc || !outdesc) goto fail; - udrive_g->bulkin = alloc_bulk_pipe(usbdev, indesc); - udrive_g->bulkout = alloc_bulk_pipe(usbdev, outdesc); + udrive_g->bulkin = alloc_async_pipe(usbdev, indesc); + udrive_g->bulkout = alloc_async_pipe(usbdev, outdesc); if (!udrive_g->bulkin || !udrive_g->bulkout) goto fail;
diff --git a/src/usb.c b/src/usb.c index 3eaa289..50f8b50 100644 --- a/src/usb.c +++ b/src/usb.c @@ -36,34 +36,66 @@ free_pipe(struct usb_pipe *pipe) cntl->freelist = pipe; }
+// Fill "pipe" endpoint info from an endpoint descriptor. +static void +desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + memset(pipe, 0, sizeof(*pipe)); + pipe->cntl = usbdev->hub->cntl; + pipe->type = usbdev->hub->cntl->type; + pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + pipe->devaddr = usbdev->devaddr; + pipe->speed = usbdev->speed; + pipe->maxpacket = epdesc->wMaxPacketSize; + pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + struct usbdevice_s *hubdev = usbdev->hub->usbdev; + if (hubdev) { + if (hubdev->defpipe->speed == USB_HIGHSPEED) { + pipe->tt_devaddr = usbdev->devaddr; + pipe->tt_port = usbdev->port; + } else { + pipe->tt_devaddr = hubdev->defpipe->tt_devaddr; + pipe->tt_port = hubdev->defpipe->tt_port; + } + } else { + pipe->tt_devaddr = pipe->tt_port = 0; + } +} + // Allocate an async pipe (control or bulk). -static struct usb_pipe * -alloc_async_pipe(struct usb_pipe *dummy) +struct usb_pipe * +alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { + struct usb_pipe dummy; + desc2pipe(&dummy, usbdev, epdesc); + // Check for an available pipe on the freelist. - struct usb_pipe **pfree = &dummy->cntl->freelist; + struct usb_pipe **pfree = &dummy.cntl->freelist; for (;;) { struct usb_pipe *pipe = *pfree; if (!pipe) break; - if (pipe->eptype == dummy->eptype) { + if (pipe->eptype == dummy.eptype) { // Use previously allocated pipe. *pfree = pipe->freenext; - memcpy(pipe, dummy, sizeof(*pipe)); + memcpy(pipe, &dummy, sizeof(*pipe)); return pipe; } pfree = &pipe->freenext; }
// Allocate a new pipe. - switch (dummy->type) { + switch (dummy.type) { default: case USB_TYPE_UHCI: - return uhci_alloc_async_pipe(dummy); + return uhci_alloc_async_pipe(&dummy); case USB_TYPE_OHCI: - return ohci_alloc_async_pipe(dummy); + return ohci_alloc_async_pipe(&dummy); case USB_TYPE_EHCI: - return ehci_alloc_async_pipe(dummy); + return ehci_alloc_async_pipe(&dummy); } }
@@ -84,26 +116,6 @@ send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize } }
-// Fill "pipe" endpoint info from an endpoint descriptor. -static void -desc2pipe(struct usb_pipe *newpipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - memcpy(newpipe, usbdev->defpipe, sizeof(*newpipe)); - newpipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - newpipe->maxpacket = epdesc->wMaxPacketSize; -} - -struct usb_pipe * -alloc_bulk_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - struct usb_pipe dummy; - desc2pipe(&dummy, usbdev, epdesc); - dummy.eptype = USB_ENDPOINT_XFER_BULK; - return alloc_async_pipe(&dummy); -} - int usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) { @@ -250,54 +262,41 @@ static int usb_set_address(struct usbdevice_s *usbdev) { ASSERT32FLAT(); - struct usbhub_s *hub = usbdev->hub; - struct usb_s *cntl = hub->cntl; + struct usb_s *cntl = usbdev->hub->cntl; dprintf(3, "set_address %p\n", cntl); if (cntl->maxaddr >= USB_MAXADDR) return -1;
// Create a pipe for the default address. - struct usb_pipe dummy; - memset(&dummy, 0, sizeof(dummy)); - dummy.cntl = cntl; - dummy.type = cntl->type; - dummy.maxpacket = 8; - dummy.eptype = USB_ENDPOINT_XFER_CONTROL; - struct usb_pipe *defpipe = alloc_async_pipe(&dummy); - if (!defpipe) + struct usb_endpoint_descriptor epdesc = { + .wMaxPacketSize = 8, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + }; + usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + if (!usbdev->defpipe) return -1; - usbdev->defpipe = defpipe; - defpipe->speed = usbdev->speed; - if (hub->usbdev) { - if (hub->usbdev->defpipe->speed == USB_HIGHSPEED) { - defpipe->tt_devaddr = hub->usbdev->defpipe->devaddr; - defpipe->tt_port = usbdev->port; - } else { - defpipe->tt_devaddr = hub->usbdev->defpipe->tt_devaddr; - defpipe->tt_port = hub->usbdev->defpipe->tt_port; - } - } else { - defpipe->tt_devaddr = defpipe->tt_port = 0; - }
msleep(USB_TIME_RSTRCY);
+ // Send set_address command. struct usb_ctrlrequest req; req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_SET_ADDRESS; req.wValue = cntl->maxaddr + 1; req.wIndex = 0; req.wLength = 0; - int ret = send_default_control(defpipe, &req, NULL); - if (ret) { - free_pipe(defpipe); + int ret = send_default_control(usbdev->defpipe, &req, NULL); + free_pipe(usbdev->defpipe); + if (ret) return -1; - }
msleep(USB_TIME_SETADDR_RECOVERY);
cntl->maxaddr++; - defpipe->devaddr = cntl->maxaddr; + usbdev->devaddr = cntl->maxaddr; + usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + if (!usbdev->defpipe) + return -1; return 0; }
@@ -307,12 +306,11 @@ static int configure_usb_device(struct usbdevice_s *usbdev) { ASSERT32FLAT(); - struct usb_pipe *pipe = usbdev->defpipe; - dprintf(3, "config_usb: %p\n", pipe); + dprintf(3, "config_usb: %p\n", usbdev->defpipe);
// Set the max packet size for endpoint 0 of this device. struct usb_device_descriptor dinfo; - int ret = get_device_info8(pipe, &dinfo); + int ret = get_device_info8(usbdev->defpipe, &dinfo); if (ret) return 0; dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n" @@ -320,10 +318,17 @@ configure_usb_device(struct usbdevice_s *usbdev) , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0); if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64) return 0; - pipe->maxpacket = dinfo.bMaxPacketSize0; + free_pipe(usbdev->defpipe); + struct usb_endpoint_descriptor epdesc = { + .wMaxPacketSize = dinfo.bMaxPacketSize0, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + }; + usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + if (!usbdev->defpipe) + return -1;
// Get configuration - struct usb_config_descriptor *config = get_device_config(pipe); + struct usb_config_descriptor *config = get_device_config(usbdev->defpipe); if (!config) return 0;
@@ -337,7 +342,7 @@ configure_usb_device(struct usbdevice_s *usbdev) goto fail;
// Set the configuration. - ret = set_configuration(pipe, config->bConfigurationValue); + ret = set_configuration(usbdev->defpipe, config->bConfigurationValue); if (ret) goto fail;
diff --git a/src/usb.h b/src/usb.h index 90b727a..fff54e5 100644 --- a/src/usb.h +++ b/src/usb.h @@ -29,6 +29,7 @@ struct usbdevice_s { struct usb_interface_descriptor *iface; int imax; u8 speed; + u8 devaddr; };
// Common information for usb controllers. @@ -217,8 +218,8 @@ int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *re , void *data); int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); void free_pipe(struct usb_pipe *pipe); -struct usb_pipe *alloc_bulk_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); int usb_poll_intr(struct usb_pipe *pipe, void *data);
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 19 ++++++++++++++----- src/usb-ehci.h | 5 ++++- src/usb-ohci.c | 17 +++++++++++++---- src/usb-ohci.h | 5 ++++- src/usb-uhci.c | 21 +++++++++++++++------ src/usb-uhci.h | 5 ++++- src/usb.c | 41 +++++++++++++++++++---------------------- src/usb.h | 3 +++ 8 files changed, 76 insertions(+), 40 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 6115610..9721568 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -422,17 +422,26 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) }
struct usb_pipe * -ehci_alloc_async_pipe(struct usb_pipe *dummy) +ehci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_EHCI) return NULL; struct usb_ehci_s *cntl = container_of( - dummy->cntl, struct usb_ehci_s, usb); - dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype); + usbdev->hub->cntl, struct usb_ehci_s, usb); + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); + + struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + usb_desc2pipe(usbpipe, usbdev, epdesc); + return usbpipe; + }
// Allocate a new queue head. struct ehci_pipe *pipe; - if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) + if (eptype == USB_ENDPOINT_XFER_CONTROL) pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); else pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); @@ -441,7 +450,7 @@ ehci_alloc_async_pipe(struct usb_pipe *dummy) return NULL; } memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
// Add queue head to controller list. diff --git a/src/usb-ehci.h b/src/usb-ehci.h index a4fbb77..ed2c3f7 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -3,8 +3,11 @@
// usb-ehci.c int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *ehci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; -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); int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 9522309..8703b26 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -319,18 +319,27 @@ wait_ed(struct ohci_ed *ed) }
struct usb_pipe * -ohci_alloc_async_pipe(struct usb_pipe *dummy) +ohci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_OHCI) return NULL; - if (dummy->eptype != USB_ENDPOINT_XFER_CONTROL) { + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (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); + usbdev->hub->cntl, struct usb_ohci_s, usb); dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
+ struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + usb_desc2pipe(usbpipe, usbdev, epdesc); + return usbpipe; + } + // Allocate a new queue head. struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); if (!pipe) { @@ -338,7 +347,7 @@ ohci_alloc_async_pipe(struct usb_pipe *dummy) return NULL; } memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); pipe->ed.hwINFO = ED_SKIP;
// Add queue head to controller list. diff --git a/src/usb-ohci.h b/src/usb-ohci.h index 6085355..bc6eb7b 100644 --- a/src/usb-ohci.h +++ b/src/usb-ohci.h @@ -3,8 +3,11 @@
// usb-ohci.c void ohci_init(struct pci_device *pci, int busid); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *ohci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; -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); int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 1c911c6..0da4eff 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -293,17 +293,26 @@ wait_pipe(struct uhci_pipe *pipe, int timeout) }
struct usb_pipe * -uhci_alloc_async_pipe(struct usb_pipe *dummy) +uhci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_UHCI) return NULL; struct usb_uhci_s *cntl = container_of( - dummy->cntl, struct usb_uhci_s, usb); - dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype); + usbdev->hub->cntl, struct usb_uhci_s, usb); + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); + + struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); + if (usbpipe) { + // Use previously allocated pipe. + usb_desc2pipe(usbpipe, usbdev, epdesc); + return usbpipe; + }
// Allocate a new queue head. struct uhci_pipe *pipe; - if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) + if (eptype == USB_ENDPOINT_XFER_CONTROL) pipe = malloc_tmphigh(sizeof(*pipe)); else pipe = malloc_low(sizeof(*pipe)); @@ -312,7 +321,7 @@ uhci_alloc_async_pipe(struct usb_pipe *dummy) return NULL; } memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); pipe->qh.element = UHCI_PTR_TERM; pipe->iobase = cntl->iobase;
@@ -321,7 +330,7 @@ uhci_alloc_async_pipe(struct usb_pipe *dummy) pipe->qh.link = control_qh->link; barrier(); control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) + if (eptype == USB_ENDPOINT_XFER_CONTROL) cntl->control_qh = &pipe->qh; return &pipe->pipe; } diff --git a/src/usb-uhci.h b/src/usb-uhci.h index 0706e8f..035a565 100644 --- a/src/usb-uhci.h +++ b/src/usb-uhci.h @@ -3,8 +3,11 @@
// usb-uhci.c void uhci_init(struct pci_device *pci, int busid); +struct usbdevice_s; +struct usb_endpoint_descriptor; +struct usb_pipe *uhci_alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; -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); int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); diff --git a/src/usb.c b/src/usb.c index 50f8b50..b61fbc1 100644 --- a/src/usb.c +++ b/src/usb.c @@ -37,11 +37,10 @@ free_pipe(struct usb_pipe *pipe) }
// Fill "pipe" endpoint info from an endpoint descriptor. -static void -desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +void +usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { - memset(pipe, 0, sizeof(*pipe)); pipe->cntl = usbdev->hub->cntl; pipe->type = usbdev->hub->cntl->type; pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; @@ -64,38 +63,36 @@ desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev } }
-// Allocate an async pipe (control or bulk). +// Check for an available pipe on the freelist. struct usb_pipe * -alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +usb_getFreePipe(struct usb_s *cntl, u8 eptype) { - struct usb_pipe dummy; - desc2pipe(&dummy, usbdev, epdesc); - - // Check for an available pipe on the freelist. - struct usb_pipe **pfree = &dummy.cntl->freelist; + struct usb_pipe **pfree = &cntl->freelist; for (;;) { struct usb_pipe *pipe = *pfree; if (!pipe) - break; - if (pipe->eptype == dummy.eptype) { - // Use previously allocated pipe. + return NULL; + if (pipe->eptype == eptype) { *pfree = pipe->freenext; - memcpy(pipe, &dummy, sizeof(*pipe)); return pipe; } pfree = &pipe->freenext; } +}
- // Allocate a new pipe. - switch (dummy.type) { +// Allocate an async pipe (control or bulk). +struct usb_pipe * +alloc_async_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + switch (usbdev->hub->cntl->type) { default: case USB_TYPE_UHCI: - return uhci_alloc_async_pipe(&dummy); + return uhci_alloc_async_pipe(usbdev, epdesc); case USB_TYPE_OHCI: - return ohci_alloc_async_pipe(&dummy); + return ohci_alloc_async_pipe(usbdev, epdesc); case USB_TYPE_EHCI: - return ehci_alloc_async_pipe(&dummy); + return ehci_alloc_async_pipe(usbdev, epdesc); } }
@@ -135,7 +132,7 @@ alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { struct usb_pipe dummy; - desc2pipe(&dummy, usbdev, epdesc); + usb_desc2pipe(&dummy, usbdev, epdesc); // Find the exponential period of the requested time. int period = epdesc->bInterval; int frameexp; diff --git a/src/usb.h b/src/usb.h index fff54e5..c792376 100644 --- a/src/usb.h +++ b/src/usb.h @@ -218,6 +218,9 @@ int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *re , void *data); int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); void free_pipe(struct usb_pipe *pipe); +void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); struct usb_pipe *alloc_async_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 10 ++++++---- src/usb-ehci.h | 3 ++- src/usb-ohci.c | 14 ++++++++------ src/usb-ohci.h | 3 ++- src/usb-uhci.c | 14 ++++++++------ src/usb-uhci.h | 3 ++- src/usb.c | 28 +++++++++++++++------------- src/usb.h | 2 ++ 8 files changed, 45 insertions(+), 32 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 9721568..477b1cf 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -621,17 +621,19 @@ 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) +ehci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_EHCI) return NULL; struct usb_ehci_s *cntl = container_of( - dummy->cntl, struct usb_ehci_s, usb); + usbdev->hub->cntl, struct usb_ehci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
if (frameexp > 10) frameexp = 10; - int maxpacket = dummy->maxpacket; + int maxpacket = epdesc->wMaxPacketSize; // Determine number of entries needed for 2 timer ticks. int ms = 1<<frameexp; int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); @@ -643,7 +645,7 @@ ehci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp) goto fail; } memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); pipe->next_td = pipe->tds = tds; pipe->data = data;
diff --git a/src/usb-ehci.h b/src/usb-ehci.h index ed2c3f7..958f444 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -11,7 +11,8 @@ struct usb_pipe; int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); 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); +struct usb_pipe *ehci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); int ehci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 8703b26..a012c6c 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -425,19 +425,19 @@ 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) +ohci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_OHCI) return NULL; struct usb_ohci_s *cntl = container_of( - dummy->cntl, struct usb_ohci_s, usb); + usbdev->hub->cntl, struct usb_ohci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
if (frameexp > 5) frameexp = 5; - int maxpacket = dummy->maxpacket; - int lowspeed = dummy->speed; - int devaddr = dummy->devaddr | (dummy->ep << 7); + int maxpacket = epdesc->wMaxPacketSize; // Determine number of entries needed for 2 timer ticks. int ms = 1<<frameexp; int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms)+1; @@ -447,7 +447,9 @@ ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp) if (!pipe || !tds || !data) goto err; memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); pipe->data = data; pipe->count = count; pipe->tds = tds; diff --git a/src/usb-ohci.h b/src/usb-ohci.h index bc6eb7b..ab957e6 100644 --- a/src/usb-ohci.h +++ b/src/usb-ohci.h @@ -11,7 +11,8 @@ struct usb_pipe; int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); 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); +struct usb_pipe *ohci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); int ohci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 0da4eff..50d98fc 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -475,19 +475,19 @@ fail: }
struct usb_pipe * -uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp) +uhci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_UHCI) return NULL; struct usb_uhci_s *cntl = container_of( - dummy->cntl, struct usb_uhci_s, usb); + usbdev->hub->cntl, struct usb_uhci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
if (frameexp > 10) frameexp = 10; - int maxpacket = dummy->maxpacket; - int lowspeed = dummy->speed; - int devaddr = dummy->devaddr | (dummy->ep << 7); + int maxpacket = epdesc->wMaxPacketSize; // Determine number of entries needed for 2 timer ticks. int ms = 1<<frameexp; int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); @@ -500,7 +500,9 @@ uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp) goto fail; } memset(pipe, 0, sizeof(*pipe)); - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); pipe->qh.element = (u32)tds; pipe->next_td = &tds[0]; pipe->iobase = cntl->iobase; diff --git a/src/usb-uhci.h b/src/usb-uhci.h index 035a565..708ba59 100644 --- a/src/usb-uhci.h +++ b/src/usb-uhci.h @@ -11,7 +11,8 @@ struct usb_pipe; int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); 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); +struct usb_pipe *uhci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); int uhci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb.c b/src/usb.c index b61fbc1..7276e15 100644 --- a/src/usb.c +++ b/src/usb.c @@ -127,27 +127,29 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) } }
-struct usb_pipe * -alloc_intr_pipe(struct usbdevice_s *usbdev +// Find the exponential period of the requested interrupt end point. +int +usb_getFrameExp(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { - struct usb_pipe dummy; - usb_desc2pipe(&dummy, usbdev, epdesc); - // Find the exponential period of the requested time. int period = epdesc->bInterval; - int frameexp; if (usbdev->speed != USB_HIGHSPEED) - frameexp = (period <= 0) ? 0 : __fls(period); - else - frameexp = (period <= 4) ? 0 : period - 4; - switch (dummy.type) { + return (period <= 0) ? 0 : __fls(period); + return (period <= 4) ? 0 : period - 4; +} + +struct usb_pipe * +alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + switch (usbdev->hub->cntl->type) { default: case USB_TYPE_UHCI: - return uhci_alloc_intr_pipe(&dummy, frameexp); + return uhci_alloc_intr_pipe(usbdev, epdesc); case USB_TYPE_OHCI: - return ohci_alloc_intr_pipe(&dummy, frameexp); + return ohci_alloc_intr_pipe(usbdev, epdesc); case USB_TYPE_EHCI: - return ehci_alloc_intr_pipe(&dummy, frameexp); + return ehci_alloc_intr_pipe(usbdev, epdesc); } }
diff --git a/src/usb.h b/src/usb.h index c792376..eddf9af 100644 --- a/src/usb.h +++ b/src/usb.h @@ -223,6 +223,8 @@ void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); struct usb_pipe *alloc_async_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); +int usb_getFrameExp(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); int usb_poll_intr(struct usb_pipe *pipe, void *data);
No code changes - just movement of code to place pipe allocater functions next to each other.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 222 +++++++++++++++++++++++++++--------------------------- src/usb-ohci.c | 158 +++++++++++++++++++------------------- src/usb-uhci.c | 228 ++++++++++++++++++++++++++++---------------------------- 3 files changed, 304 insertions(+), 304 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 477b1cf..67b8450 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -380,45 +380,80 @@ ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) * End point communication ****************************************************************/
-static void -ehci_reset_pipe(struct ehci_pipe *pipe) +struct usb_pipe * +ehci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { - SET_FLATPTR(pipe->qh.qtd_next, EHCI_PTR_TERM); - SET_FLATPTR(pipe->qh.alt_next, EHCI_PTR_TERM); - barrier(); - SET_FLATPTR(pipe->qh.token, GET_FLATPTR(pipe->qh.token) & QTD_TOGGLE); -} + if (! CONFIG_USB_EHCI) + return NULL; + struct usb_ehci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ehci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
-static int -ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) -{ - u64 end = calc_future_tsc(timeout); - u32 status; - for (;;) { - status = td->token; - if (!(status & QTD_STS_ACTIVE)) - break; - if (check_tsc(end)) { - u32 cur = GET_FLATPTR(pipe->qh.current); - u32 tok = GET_FLATPTR(pipe->qh.token); - u32 next = GET_FLATPTR(pipe->qh.qtd_next); - warn_timeout(); - dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n" - , pipe, cur, tok, next, td, status); - ehci_reset_pipe(pipe); - struct usb_ehci_s *cntl = container_of( - GET_FLATPTR(pipe->pipe.cntl), struct usb_ehci_s, usb); - ehci_waittick(cntl); - return -1; - } - yield(); + if (frameexp > 10) + frameexp = 10; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<<frameexp; + int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); + struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); + struct ehci_qtd *tds = memalign_low(EHCI_QTD_ALIGN, sizeof(*tds) * count); + void *data = malloc_low(maxpacket * count); + if (!pipe || !tds || !data) { + warn_noalloc(); + goto fail; } - if (status & QTD_STS_HALT) { - dprintf(1, "ehci_wait_td error - status=%x\n", status); - ehci_reset_pipe(pipe); - return -2; + memset(pipe, 0, sizeof(*pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + pipe->next_td = pipe->tds = tds; + pipe->data = data; + + pipe->qh.info1 = ( + (1 << QH_MULT_SHIFT) + | (maxpacket << QH_MAXPACKET_SHIFT) + | (pipe->pipe.speed << QH_SPEED_SHIFT) + | (pipe->pipe.ep << QH_EP_SHIFT) + | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); + pipe->qh.info2 = ((1 << QH_MULT_SHIFT) + | (pipe->pipe.tt_port << QH_HUBPORT_SHIFT) + | (pipe->pipe.tt_devaddr << QH_HUBADDR_SHIFT) + | (0x01 << QH_SMASK_SHIFT) + | (0x1c << QH_CMASK_SHIFT)); + pipe->qh.qtd_next = (u32)tds; + + int i; + for (i=0; i<count; i++) { + struct ehci_qtd *td = &tds[i]; + td->qtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]); + td->alt_next = EHCI_PTR_TERM; + td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE + | QTD_PID_IN | ehci_maxerr(3)); + td->buf[0] = (u32)data + maxpacket * i; } - return 0; + + // Add to interrupt schedule. + struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase); + if (frameexp == 0) { + // Add to existing interrupt entry. + struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS); + pipe->qh.next = intr_qh->next; + barrier(); + intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; + } else { + int startpos = 1<<(frameexp-1); + pipe->qh.next = fl->links[startpos]; + barrier(); + for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) + fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH; + } + + return &pipe->pipe; +fail: + free(pipe); + free(tds); + free(data); + return NULL; }
struct usb_pipe * @@ -461,6 +496,47 @@ ehci_alloc_async_pipe(struct usbdevice_s *usbdev return &pipe->pipe; }
+static void +ehci_reset_pipe(struct ehci_pipe *pipe) +{ + SET_FLATPTR(pipe->qh.qtd_next, EHCI_PTR_TERM); + SET_FLATPTR(pipe->qh.alt_next, EHCI_PTR_TERM); + barrier(); + SET_FLATPTR(pipe->qh.token, GET_FLATPTR(pipe->qh.token) & QTD_TOGGLE); +} + +static int +ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) +{ + u64 end = calc_future_tsc(timeout); + u32 status; + for (;;) { + status = td->token; + if (!(status & QTD_STS_ACTIVE)) + break; + if (check_tsc(end)) { + u32 cur = GET_FLATPTR(pipe->qh.current); + u32 tok = GET_FLATPTR(pipe->qh.token); + u32 next = GET_FLATPTR(pipe->qh.qtd_next); + warn_timeout(); + dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n" + , pipe, cur, tok, next, td, status); + ehci_reset_pipe(pipe); + struct usb_ehci_s *cntl = container_of( + GET_FLATPTR(pipe->pipe.cntl), struct usb_ehci_s, usb); + ehci_waittick(cntl); + return -1; + } + yield(); + } + if (status & QTD_STS_HALT) { + dprintf(1, "ehci_wait_td error - status=%x\n", status); + ehci_reset_pipe(pipe); + return -2; + } + return 0; +} + static int fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes) { @@ -620,82 +696,6 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) return 0; }
-struct usb_pipe * -ehci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_EHCI) - return NULL; - struct usb_ehci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ehci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 10) - frameexp = 10; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<<frameexp; - int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); - struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); - struct ehci_qtd *tds = memalign_low(EHCI_QTD_ALIGN, sizeof(*tds) * count); - void *data = malloc_low(maxpacket * count); - if (!pipe || !tds || !data) { - warn_noalloc(); - goto fail; - } - memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - pipe->next_td = pipe->tds = tds; - pipe->data = data; - - pipe->qh.info1 = ( - (1 << QH_MULT_SHIFT) - | (maxpacket << QH_MAXPACKET_SHIFT) - | (pipe->pipe.speed << QH_SPEED_SHIFT) - | (pipe->pipe.ep << QH_EP_SHIFT) - | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); - pipe->qh.info2 = ((1 << QH_MULT_SHIFT) - | (pipe->pipe.tt_port << QH_HUBPORT_SHIFT) - | (pipe->pipe.tt_devaddr << QH_HUBADDR_SHIFT) - | (0x01 << QH_SMASK_SHIFT) - | (0x1c << QH_CMASK_SHIFT)); - pipe->qh.qtd_next = (u32)tds; - - int i; - for (i=0; i<count; i++) { - struct ehci_qtd *td = &tds[i]; - td->qtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]); - td->alt_next = EHCI_PTR_TERM; - td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE - | QTD_PID_IN | ehci_maxerr(3)); - td->buf[0] = (u32)data + maxpacket * i; - } - - // Add to interrupt schedule. - struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase); - if (frameexp == 0) { - // Add to existing interrupt entry. - struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS); - pipe->qh.next = intr_qh->next; - barrier(); - intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; - } else { - int startpos = 1<<(frameexp-1); - pipe->qh.next = fl->links[startpos]; - barrier(); - for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) - fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH; - } - - return &pipe->pipe; -fail: - free(pipe); - free(tds); - free(data); - return NULL; -} - int ehci_poll_intr(struct usb_pipe *p, void *data) { diff --git a/src/usb-ohci.c b/src/usb-ohci.c index a012c6c..39ed92a 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -302,20 +302,71 @@ ohci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
-static int -wait_ed(struct ohci_ed *ed) +struct usb_pipe * +ohci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { - // XXX - 500ms just a guess - u64 end = calc_future_tsc(500); - for (;;) { - if (ed->hwHeadP == ed->hwTailP) - return 0; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); + if (! CONFIG_USB_OHCI) + return NULL; + struct usb_ohci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_ohci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); + + if (frameexp > 5) + frameexp = 5; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<<frameexp; + int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms)+1; + struct ohci_pipe *pipe = malloc_low(sizeof(*pipe)); + struct ohci_td *tds = malloc_low(sizeof(*tds) * count); + void *data = malloc_low(maxpacket * count); + if (!pipe || !tds || !data) + goto err; + memset(pipe, 0, sizeof(*pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); + pipe->data = data; + pipe->count = count; + pipe->tds = tds; + + struct ohci_ed *ed = &pipe->ed; + ed->hwHeadP = (u32)&tds[0]; + ed->hwTailP = (u32)&tds[count-1]; + ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0); + + int i; + for (i=0; i<count-1; i++) { + tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC; + tds[i].hwCBP = (u32)data + maxpacket * i; + tds[i].hwNextTD = (u32)&tds[i+1]; + tds[i].hwBE = tds[i].hwCBP + maxpacket - 1; } + + // Add to interrupt schedule. + barrier(); + struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + if (frameexp == 0) { + // Add to existing interrupt entry. + struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; + ed->hwNextED = intr_ed->hwNextED; + intr_ed->hwNextED = (u32)ed; + } else { + int startpos = 1<<(frameexp-1); + ed->hwNextED = hcca->int_table[startpos]; + for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms) + hcca->int_table[i] = (u32)ed; + } + + return &pipe->pipe; + +err: + free(pipe); + free(tds); + free(data); + return NULL; }
struct usb_pipe * @@ -357,6 +408,22 @@ ohci_alloc_async_pipe(struct usbdevice_s *usbdev return &pipe->pipe; }
+static int +wait_ed(struct ohci_ed *ed) +{ + // XXX - 500ms just a guess + u64 end = calc_future_tsc(500); + for (;;) { + if (ed->hwHeadP == ed->hwTailP) + return 0; + if (check_tsc(end)) { + warn_timeout(); + return -1; + } + yield(); + } +} + int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize) @@ -424,73 +491,6 @@ ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) return -1; }
-struct usb_pipe * -ohci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_OHCI) - return NULL; - struct usb_ohci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_ohci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 5) - frameexp = 5; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<<frameexp; - int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms)+1; - struct ohci_pipe *pipe = malloc_low(sizeof(*pipe)); - struct ohci_td *tds = malloc_low(sizeof(*tds) * count); - void *data = malloc_low(maxpacket * count); - if (!pipe || !tds || !data) - goto err; - memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); - pipe->data = data; - pipe->count = count; - pipe->tds = tds; - - struct ohci_ed *ed = &pipe->ed; - ed->hwHeadP = (u32)&tds[0]; - ed->hwTailP = (u32)&tds[count-1]; - ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0); - - int i; - for (i=0; i<count-1; i++) { - tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC; - tds[i].hwCBP = (u32)data + maxpacket * i; - tds[i].hwNextTD = (u32)&tds[i+1]; - tds[i].hwBE = tds[i].hwCBP + maxpacket - 1; - } - - // Add to interrupt schedule. - barrier(); - struct ohci_hcca *hcca = (void*)cntl->regs->hcca; - if (frameexp == 0) { - // Add to existing interrupt entry. - struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; - ed->hwNextED = intr_ed->hwNextED; - intr_ed->hwNextED = (u32)ed; - } else { - int startpos = 1<<(frameexp-1); - ed->hwNextED = hcca->int_table[startpos]; - for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms) - hcca->int_table[i] = (u32)ed; - } - - return &pipe->pipe; - -err: - free(pipe); - free(tds); - free(data); - return NULL; -} - int ohci_poll_intr(struct usb_pipe *p, void *data) { diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 50d98fc..aa49681 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -268,28 +268,76 @@ uhci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
-static int -wait_pipe(struct uhci_pipe *pipe, int timeout) +struct usb_pipe * +uhci_alloc_intr_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { - u64 end = calc_future_tsc(timeout); - for (;;) { - u32 el_link = GET_FLATPTR(pipe->qh.element); - if (el_link & UHCI_PTR_TERM) - return 0; - if (check_tsc(end)) { - warn_timeout(); - u16 iobase = GET_FLATPTR(pipe->iobase); - struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS); - dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n" - , pipe, (void*)el_link, GET_FLATPTR(td->status) - , inw(iobase + USBCMD) - , inw(iobase + USBSTS)); - SET_FLATPTR(pipe->qh.element, UHCI_PTR_TERM); - uhci_waittick(iobase); - return -1; - } - yield(); + if (! CONFIG_USB_UHCI) + return NULL; + struct usb_uhci_s *cntl = container_of( + usbdev->hub->cntl, struct usb_uhci_s, usb); + int frameexp = usb_getFrameExp(usbdev, epdesc); + dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); + + if (frameexp > 10) + frameexp = 10; + int maxpacket = epdesc->wMaxPacketSize; + // Determine number of entries needed for 2 timer ticks. + int ms = 1<<frameexp; + int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); + count = ALIGN(count, 2); + struct uhci_pipe *pipe = malloc_low(sizeof(*pipe)); + struct uhci_td *tds = malloc_low(sizeof(*tds) * count); + void *data = malloc_low(maxpacket * count); + if (!pipe || !tds || !data) { + warn_noalloc(); + goto fail; + } + memset(pipe, 0, sizeof(*pipe)); + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + int lowspeed = pipe->pipe.speed; + int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); + pipe->qh.element = (u32)tds; + pipe->next_td = &tds[0]; + pipe->iobase = cntl->iobase; + + int toggle = 0; + int i; + for (i=0; i<count; i++) { + tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]); + tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) + | TD_CTRL_ACTIVE); + tds[i].token = (uhci_explen(maxpacket) | toggle + | (devaddr << TD_TOKEN_DEVADDR_SHIFT) + | USB_PID_IN); + tds[i].buffer = data + maxpacket * i; + toggle ^= TD_TOKEN_TOGGLE; } + + // Add to interrupt schedule. + struct uhci_framelist *fl = cntl->framelist; + if (frameexp == 0) { + // Add to existing interrupt entry. + struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS); + pipe->qh.link = intr_qh->link; + barrier(); + intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; + if (cntl->control_qh == intr_qh) + cntl->control_qh = &pipe->qh; + } else { + int startpos = 1<<(frameexp-1); + pipe->qh.link = fl->links[startpos]; + barrier(); + for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) + fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH; + } + + return &pipe->pipe; +fail: + free(pipe); + free(tds); + free(data); + return NULL; }
struct usb_pipe * @@ -335,6 +383,52 @@ uhci_alloc_async_pipe(struct usbdevice_s *usbdev return &pipe->pipe; }
+static int +wait_pipe(struct uhci_pipe *pipe, int timeout) +{ + u64 end = calc_future_tsc(timeout); + for (;;) { + u32 el_link = GET_FLATPTR(pipe->qh.element); + if (el_link & UHCI_PTR_TERM) + return 0; + if (check_tsc(end)) { + warn_timeout(); + u16 iobase = GET_FLATPTR(pipe->iobase); + struct uhci_td *td = (void*)(el_link & ~UHCI_PTR_BITS); + dprintf(1, "Timeout on wait_pipe %p (td=%p s=%x c=%x/%x)\n" + , pipe, (void*)el_link, GET_FLATPTR(td->status) + , inw(iobase + USBCMD) + , inw(iobase + USBSTS)); + SET_FLATPTR(pipe->qh.element, UHCI_PTR_TERM); + uhci_waittick(iobase); + return -1; + } + yield(); + } +} + +static int +wait_td(struct uhci_td *td) +{ + u64 end = calc_future_tsc(5000); // XXX - lookup real time. + u32 status; + for (;;) { + status = td->status; + if (!(status & TD_CTRL_ACTIVE)) + break; + if (check_tsc(end)) { + warn_timeout(); + return -1; + } + yield(); + } + if (status & TD_CTRL_ANY_ERROR) { + dprintf(1, "wait_td error - status=%x\n", status); + return -2; + } + return 0; +} + int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize) @@ -392,28 +486,6 @@ uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize return ret; }
-static int -wait_td(struct uhci_td *td) -{ - u64 end = calc_future_tsc(5000); // XXX - lookup real time. - u32 status; - for (;;) { - status = td->status; - if (!(status & TD_CTRL_ACTIVE)) - break; - if (check_tsc(end)) { - warn_timeout(); - return -1; - } - yield(); - } - if (status & TD_CTRL_ANY_ERROR) { - dprintf(1, "wait_td error - status=%x\n", status); - return -2; - } - return 0; -} - #define STACKTDS 4 #define TDALIGN 16
@@ -474,78 +546,6 @@ fail: return -1; }
-struct usb_pipe * -uhci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - if (! CONFIG_USB_UHCI) - return NULL; - struct usb_uhci_s *cntl = container_of( - usbdev->hub->cntl, struct usb_uhci_s, usb); - int frameexp = usb_getFrameExp(usbdev, epdesc); - dprintf(7, "uhci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); - - if (frameexp > 10) - frameexp = 10; - int maxpacket = epdesc->wMaxPacketSize; - // Determine number of entries needed for 2 timer ticks. - int ms = 1<<frameexp; - int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); - count = ALIGN(count, 2); - struct uhci_pipe *pipe = malloc_low(sizeof(*pipe)); - struct uhci_td *tds = malloc_low(sizeof(*tds) * count); - void *data = malloc_low(maxpacket * count); - if (!pipe || !tds || !data) { - warn_noalloc(); - goto fail; - } - memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); - pipe->qh.element = (u32)tds; - pipe->next_td = &tds[0]; - pipe->iobase = cntl->iobase; - - int toggle = 0; - int i; - for (i=0; i<count; i++) { - tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]); - tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0) - | TD_CTRL_ACTIVE); - tds[i].token = (uhci_explen(maxpacket) | toggle - | (devaddr << TD_TOKEN_DEVADDR_SHIFT) - | USB_PID_IN); - tds[i].buffer = data + maxpacket * i; - toggle ^= TD_TOKEN_TOGGLE; - } - - // Add to interrupt schedule. - struct uhci_framelist *fl = cntl->framelist; - if (frameexp == 0) { - // Add to existing interrupt entry. - struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS); - pipe->qh.link = intr_qh->link; - barrier(); - intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - if (cntl->control_qh == intr_qh) - cntl->control_qh = &pipe->qh; - } else { - int startpos = 1<<(frameexp-1); - pipe->qh.link = fl->links[startpos]; - barrier(); - for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) - fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH; - } - - return &pipe->pipe; -fail: - free(pipe); - free(tds); - free(data); - return NULL; -} - int uhci_poll_intr(struct usb_pipe *p, void *data) {
Use one function (X_alloc_pipe) as the main entry point for usb pipe allocation in the controller code. The determination of interrupt/bulk/control can be done within the controller.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 12 ++++++------ src/usb-ehci.h | 6 ++---- src/usb-hid.c | 4 ++-- src/usb-msc.c | 4 ++-- src/usb-ohci.c | 10 +++++----- src/usb-ohci.h | 6 ++---- src/usb-uhci.c | 12 ++++++------ src/usb-uhci.h | 6 ++---- src/usb.c | 31 ++++++++----------------------- src/usb.h | 6 ++---- 10 files changed, 37 insertions(+), 60 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 67b8450..da5ed6f 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -380,12 +380,10 @@ ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) * End point communication ****************************************************************/
-struct usb_pipe * +static struct usb_pipe * ehci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { - if (! CONFIG_USB_EHCI) - return NULL; struct usb_ehci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ehci_s, usb); int frameexp = usb_getFrameExp(usbdev, epdesc); @@ -457,14 +455,16 @@ fail: }
struct usb_pipe * -ehci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +ehci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_EHCI) return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return ehci_alloc_intr_pipe(usbdev, epdesc); struct usb_ehci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ehci_s, usb); - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); diff --git a/src/usb-ehci.h b/src/usb-ehci.h index 958f444..b295c78 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -5,14 +5,12 @@ int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci); struct usbdevice_s; struct usb_endpoint_descriptor; -struct usb_pipe *ehci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *ehci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -struct usb_pipe *ehci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); int ehci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-hid.c b/src/usb-hid.c index 21363c3..6e8ec4e 100644 --- a/src/usb-hid.c +++ b/src/usb-hid.c @@ -70,7 +70,7 @@ usb_kbd_init(struct usbdevice_s *usbdev if (ret) return -1;
- keyboard_pipe = alloc_intr_pipe(usbdev, epdesc); + keyboard_pipe = usb_alloc_pipe(usbdev, epdesc); if (!keyboard_pipe) return -1;
@@ -96,7 +96,7 @@ usb_mouse_init(struct usbdevice_s *usbdev if (ret) return -1;
- mouse_pipe = alloc_intr_pipe(usbdev, epdesc); + mouse_pipe = usb_alloc_pipe(usbdev, epdesc); if (!mouse_pipe) return -1;
diff --git a/src/usb-msc.c b/src/usb-msc.c index 4bf24a3..f6f9958 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -156,8 +156,8 @@ usb_msc_init(struct usbdevice_s *usbdev) usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); if (!indesc || !outdesc) goto fail; - udrive_g->bulkin = alloc_async_pipe(usbdev, indesc); - udrive_g->bulkout = alloc_async_pipe(usbdev, outdesc); + udrive_g->bulkin = usb_alloc_pipe(usbdev, indesc); + udrive_g->bulkout = usb_alloc_pipe(usbdev, outdesc); if (!udrive_g->bulkin || !udrive_g->bulkout) goto fail;
diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 39ed92a..a0937a2 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -302,12 +302,10 @@ ohci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
-struct usb_pipe * +static struct usb_pipe * ohci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { - if (! CONFIG_USB_OHCI) - return NULL; struct usb_ohci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ohci_s, usb); int frameexp = usb_getFrameExp(usbdev, epdesc); @@ -370,12 +368,14 @@ err: }
struct usb_pipe * -ohci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +ohci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_OHCI) return NULL; u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return ohci_alloc_intr_pipe(usbdev, epdesc); if (eptype != USB_ENDPOINT_XFER_CONTROL) { dprintf(1, "OHCI Bulk transfers not supported.\n"); return NULL; diff --git a/src/usb-ohci.h b/src/usb-ohci.h index ab957e6..25900a7 100644 --- a/src/usb-ohci.h +++ b/src/usb-ohci.h @@ -5,14 +5,12 @@ void ohci_init(struct pci_device *pci, int busid); struct usbdevice_s; struct usb_endpoint_descriptor; -struct usb_pipe *ohci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *ohci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -struct usb_pipe *ohci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); int ohci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb-uhci.c b/src/usb-uhci.c index aa49681..b2677b8 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -268,12 +268,10 @@ uhci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
-struct usb_pipe * +static struct usb_pipe * uhci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { - if (! CONFIG_USB_UHCI) - return NULL; struct usb_uhci_s *cntl = container_of( usbdev->hub->cntl, struct usb_uhci_s, usb); int frameexp = usb_getFrameExp(usbdev, epdesc); @@ -341,14 +339,16 @@ fail: }
struct usb_pipe * -uhci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +uhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_UHCI) return NULL; + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_INT) + return uhci_alloc_intr_pipe(usbdev, epdesc); struct usb_uhci_s *cntl = container_of( usbdev->hub->cntl, struct usb_uhci_s, usb); - u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); diff --git a/src/usb-uhci.h b/src/usb-uhci.h index 708ba59..9e3297c 100644 --- a/src/usb-uhci.h +++ b/src/usb-uhci.h @@ -5,14 +5,12 @@ void uhci_init(struct pci_device *pci, int busid); struct usbdevice_s; struct usb_endpoint_descriptor; -struct usb_pipe *uhci_alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *uhci_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); struct usb_pipe; int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); -struct usb_pipe *uhci_alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); int uhci_poll_intr(struct usb_pipe *p, void *data);
diff --git a/src/usb.c b/src/usb.c index 7276e15..5a5331f 100644 --- a/src/usb.c +++ b/src/usb.c @@ -82,17 +82,17 @@ usb_getFreePipe(struct usb_s *cntl, u8 eptype)
// Allocate an async pipe (control or bulk). struct usb_pipe * -alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) +usb_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) { switch (usbdev->hub->cntl->type) { default: case USB_TYPE_UHCI: - return uhci_alloc_async_pipe(usbdev, epdesc); + return uhci_alloc_pipe(usbdev, epdesc); case USB_TYPE_OHCI: - return ohci_alloc_async_pipe(usbdev, epdesc); + return ohci_alloc_pipe(usbdev, epdesc); case USB_TYPE_EHCI: - return ehci_alloc_async_pipe(usbdev, epdesc); + return ehci_alloc_pipe(usbdev, epdesc); } }
@@ -138,21 +138,6 @@ usb_getFrameExp(struct usbdevice_s *usbdev return (period <= 4) ? 0 : period - 4; }
-struct usb_pipe * -alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - switch (usbdev->hub->cntl->type) { - default: - case USB_TYPE_UHCI: - return uhci_alloc_intr_pipe(usbdev, epdesc); - case USB_TYPE_OHCI: - return ohci_alloc_intr_pipe(usbdev, epdesc); - case USB_TYPE_EHCI: - return ehci_alloc_intr_pipe(usbdev, epdesc); - } -} - int noinline usb_poll_intr(struct usb_pipe *pipe_fl, void *data) { @@ -271,7 +256,7 @@ usb_set_address(struct usbdevice_s *usbdev) .wMaxPacketSize = 8, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, }; - usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); if (!usbdev->defpipe) return -1;
@@ -293,7 +278,7 @@ usb_set_address(struct usbdevice_s *usbdev)
cntl->maxaddr++; usbdev->devaddr = cntl->maxaddr; - usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); if (!usbdev->defpipe) return -1; return 0; @@ -322,7 +307,7 @@ configure_usb_device(struct usbdevice_s *usbdev) .wMaxPacketSize = dinfo.bMaxPacketSize0, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, }; - usbdev->defpipe = alloc_async_pipe(usbdev, &epdesc); + usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); if (!usbdev->defpipe) return -1;
diff --git a/src/usb.h b/src/usb.h index eddf9af..3802c35 100644 --- a/src/usb.h +++ b/src/usb.h @@ -221,12 +221,10 @@ void free_pipe(struct usb_pipe *pipe); void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); -struct usb_pipe *alloc_async_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); +struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); int usb_getFrameExp(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); int usb_poll_intr(struct usb_pipe *pipe, void *data); struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev , int type, int dir);
Move code around to put like functions near each other.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb.c | 154 ++++++++++++++++++++++++++++++------------------------------ src/usb.h | 14 +++--- 2 files changed, 84 insertions(+), 84 deletions(-)
diff --git a/src/usb.c b/src/usb.c index 5a5331f..69231d5 100644 --- a/src/usb.c +++ b/src/usb.c @@ -23,63 +23,6 @@ * Controller function wrappers ****************************************************************/
-// Free an allocated control or bulk pipe. -void -free_pipe(struct usb_pipe *pipe) -{ - ASSERT32FLAT(); - if (!pipe) - return; - // Add to controller's free list. - struct usb_s *cntl = pipe->cntl; - pipe->freenext = cntl->freelist; - cntl->freelist = pipe; -} - -// Fill "pipe" endpoint info from an endpoint descriptor. -void -usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - pipe->cntl = usbdev->hub->cntl; - pipe->type = usbdev->hub->cntl->type; - pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - pipe->devaddr = usbdev->devaddr; - pipe->speed = usbdev->speed; - pipe->maxpacket = epdesc->wMaxPacketSize; - pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - struct usbdevice_s *hubdev = usbdev->hub->usbdev; - if (hubdev) { - if (hubdev->defpipe->speed == USB_HIGHSPEED) { - pipe->tt_devaddr = usbdev->devaddr; - pipe->tt_port = usbdev->port; - } else { - pipe->tt_devaddr = hubdev->defpipe->tt_devaddr; - pipe->tt_port = hubdev->defpipe->tt_port; - } - } else { - pipe->tt_devaddr = pipe->tt_port = 0; - } -} - -// Check for an available pipe on the freelist. -struct usb_pipe * -usb_getFreePipe(struct usb_s *cntl, u8 eptype) -{ - struct usb_pipe **pfree = &cntl->freelist; - for (;;) { - struct usb_pipe *pipe = *pfree; - if (!pipe) - return NULL; - if (pipe->eptype == eptype) { - *pfree = pipe->freenext; - return pipe; - } - pfree = &pipe->freenext; - } -} - // Allocate an async pipe (control or bulk). struct usb_pipe * usb_alloc_pipe(struct usbdevice_s *usbdev @@ -127,17 +70,6 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) } }
-// Find the exponential period of the requested interrupt end point. -int -usb_getFrameExp(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc) -{ - int period = epdesc->bInterval; - if (usbdev->speed != USB_HIGHSPEED) - return (period <= 0) ? 0 : __fls(period); - return (period <= 4) ? 0 : period - 4; -} - int noinline usb_poll_intr(struct usb_pipe *pipe_fl, void *data) { @@ -157,6 +89,83 @@ usb_poll_intr(struct usb_pipe *pipe_fl, void *data) * Helper functions ****************************************************************/
+// Send a message to the default control pipe of a device. +int +send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req + , void *data) +{ + return send_control(pipe, req->bRequestType & USB_DIR_IN + , req, sizeof(*req), data, req->wLength); +} + +// Free an allocated control or bulk pipe. +void +free_pipe(struct usb_pipe *pipe) +{ + ASSERT32FLAT(); + if (!pipe) + return; + // Add to controller's free list. + struct usb_s *cntl = pipe->cntl; + pipe->freenext = cntl->freelist; + cntl->freelist = pipe; +} + +// Check for an available pipe on the freelist. +struct usb_pipe * +usb_getFreePipe(struct usb_s *cntl, u8 eptype) +{ + struct usb_pipe **pfree = &cntl->freelist; + for (;;) { + struct usb_pipe *pipe = *pfree; + if (!pipe) + return NULL; + if (pipe->eptype == eptype) { + *pfree = pipe->freenext; + return pipe; + } + pfree = &pipe->freenext; + } +} + +// Fill "pipe" endpoint info from an endpoint descriptor. +void +usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + pipe->cntl = usbdev->hub->cntl; + pipe->type = usbdev->hub->cntl->type; + pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + pipe->devaddr = usbdev->devaddr; + pipe->speed = usbdev->speed; + pipe->maxpacket = epdesc->wMaxPacketSize; + pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + struct usbdevice_s *hubdev = usbdev->hub->usbdev; + if (hubdev) { + if (hubdev->defpipe->speed == USB_HIGHSPEED) { + pipe->tt_devaddr = usbdev->devaddr; + pipe->tt_port = usbdev->port; + } else { + pipe->tt_devaddr = hubdev->defpipe->tt_devaddr; + pipe->tt_port = hubdev->defpipe->tt_port; + } + } else { + pipe->tt_devaddr = pipe->tt_port = 0; + } +} + +// Find the exponential period of the requested interrupt end point. +int +usb_getFrameExp(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + int period = epdesc->bInterval; + if (usbdev->speed != USB_HIGHSPEED) + return (period <= 0) ? 0 : __fls(period); + return (period <= 4) ? 0 : period - 4; +} + // Find the first endpoing of a given type in an interface description. struct usb_endpoint_descriptor * findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir) @@ -175,15 +184,6 @@ findEndPointDesc(struct usbdevice_s *usbdev, int type, int dir) } }
-// Send a message to the default control pipe of a device. -int -send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req - , void *data) -{ - return send_control(pipe, req->bRequestType & USB_DIR_IN - , req, sizeof(*req), data, req->wLength); -} - // Get the first 8 bytes of the device descriptor. static int get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo) diff --git a/src/usb.h b/src/usb.h index 3802c35..72f2a7c 100644 --- a/src/usb.h +++ b/src/usb.h @@ -212,21 +212,21 @@ struct usb_endpoint_descriptor { ****************************************************************/
// usb.c -void usb_setup(void); -void usb_enumerate(struct usbhub_s *hub); +struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc); +int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize); +int usb_poll_intr(struct usb_pipe *pipe, void *data); 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); void free_pipe(struct usb_pipe *pipe); +struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); -struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype); -struct usb_pipe *usb_alloc_pipe(struct usbdevice_s *usbdev - , struct usb_endpoint_descriptor *epdesc); int usb_getFrameExp(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc); -int usb_poll_intr(struct usb_pipe *pipe, void *data); struct usb_endpoint_descriptor *findEndPointDesc(struct usbdevice_s *usbdev , int type, int dir); +void usb_enumerate(struct usbhub_s *hub); +void usb_setup(void);
#endif // usb.h
Move the code to setup the ehci specific queue head fields to the ehci code. Also, setup the ehci queue head fields once during pipe allocation instead of on each transfer.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 85 +++++++++++++++++++++++++++----------------------------- src/usb.c | 13 -------- src/usb.h | 2 - 3 files changed, 41 insertions(+), 59 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index da5ed6f..a99ac35 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -380,6 +380,40 @@ ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) * End point communication ****************************************************************/
+// Setup fields in qh +static void +ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + + pipe->qh.info1 = ( + (1 << QH_MULT_SHIFT) + | (pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT) + | (pipe->pipe.speed << QH_SPEED_SHIFT) + | (pipe->pipe.ep << QH_EP_SHIFT) + | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); + + pipe->qh.info2 = (1 << QH_MULT_SHIFT); + struct usbdevice_s *hubdev = usbdev->hub->usbdev; + if (hubdev) { + struct ehci_pipe *hpipe = container_of( + hubdev->defpipe, struct ehci_pipe, pipe); + if (hpipe->pipe.speed == USB_HIGHSPEED) + pipe->qh.info2 |= ((usbdev->port << QH_HUBPORT_SHIFT) + | (hpipe->pipe.devaddr << QH_HUBADDR_SHIFT)); + else + pipe->qh.info2 = hpipe->qh.info2; + } + + u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (eptype == USB_ENDPOINT_XFER_CONTROL) + pipe->qh.info1 |= ((pipe->pipe.speed != USB_HIGHSPEED ? QH_CONTROL : 0) + | QH_TOGGLECONTROL); + else if (eptype == USB_ENDPOINT_XFER_INT) + pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT); +} + static struct usb_pipe * ehci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) @@ -403,21 +437,9 @@ ehci_alloc_intr_pipe(struct usbdevice_s *usbdev goto fail; } memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + ehci_desc2pipe(pipe, usbdev, epdesc); pipe->next_td = pipe->tds = tds; pipe->data = data; - - pipe->qh.info1 = ( - (1 << QH_MULT_SHIFT) - | (maxpacket << QH_MAXPACKET_SHIFT) - | (pipe->pipe.speed << QH_SPEED_SHIFT) - | (pipe->pipe.ep << QH_EP_SHIFT) - | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); - pipe->qh.info2 = ((1 << QH_MULT_SHIFT) - | (pipe->pipe.tt_port << QH_HUBPORT_SHIFT) - | (pipe->pipe.tt_devaddr << QH_HUBADDR_SHIFT) - | (0x01 << QH_SMASK_SHIFT) - | (0x1c << QH_CMASK_SHIFT)); pipe->qh.qtd_next = (u32)tds;
int i; @@ -470,7 +492,8 @@ ehci_alloc_pipe(struct usbdevice_s *usbdev struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); if (usbpipe) { // Use previously allocated pipe. - usb_desc2pipe(usbpipe, usbdev, epdesc); + struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); + ehci_desc2pipe(pipe, usbdev, epdesc); return usbpipe; }
@@ -485,7 +508,7 @@ ehci_alloc_pipe(struct usbdevice_s *usbdev return NULL; } memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + ehci_desc2pipe(pipe, usbdev, epdesc); pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
// Add queue head to controller list. @@ -575,21 +598,6 @@ ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize } struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
- u16 maxpacket = pipe->pipe.maxpacket; - int speed = pipe->pipe.speed; - - // Setup fields in qh - pipe->qh.info1 = ( - (1 << QH_MULT_SHIFT) | (speed != USB_HIGHSPEED ? QH_CONTROL : 0) - | (maxpacket << QH_MAXPACKET_SHIFT) - | QH_TOGGLECONTROL - | (speed << QH_SPEED_SHIFT) - | (pipe->pipe.ep << QH_EP_SHIFT) - | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); - pipe->qh.info2 = ((1 << QH_MULT_SHIFT) - | (pipe->pipe.tt_port << QH_HUBPORT_SHIFT) - | (pipe->pipe.tt_devaddr << QH_HUBADDR_SHIFT)); - // Setup transfer descriptors struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3); if (!tds) { @@ -603,6 +611,7 @@ ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize td->alt_next = EHCI_PTR_TERM; td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE | QTD_PID_SETUP | ehci_maxerr(3)); + u16 maxpacket = pipe->pipe.maxpacket; fillTDbuffer(td, maxpacket, cmd, cmdsize); td++;
@@ -645,26 +654,14 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" , &pipe->qh, dir, data, datasize);
- // Allocate 4 tds on stack (16byte aligned) + // Allocate 4 tds on stack (with required alignment) u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1]; struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN); memset(tds, 0, sizeof(*tds) * STACKQTDS); - - // Setup fields in qh - u16 maxpacket = GET_FLATPTR(pipe->pipe.maxpacket); - SET_FLATPTR(pipe->qh.info1 - , ((1 << QH_MULT_SHIFT) - | (maxpacket << QH_MAXPACKET_SHIFT) - | (GET_FLATPTR(pipe->pipe.speed) << QH_SPEED_SHIFT) - | (GET_FLATPTR(pipe->pipe.ep) << QH_EP_SHIFT) - | (GET_FLATPTR(pipe->pipe.devaddr) << QH_DEVADDR_SHIFT))); - SET_FLATPTR(pipe->qh.info2 - , ((1 << QH_MULT_SHIFT) - | (GET_FLATPTR(pipe->pipe.tt_port) << QH_HUBPORT_SHIFT) - | (GET_FLATPTR(pipe->pipe.tt_devaddr) << QH_HUBADDR_SHIFT))); barrier(); SET_FLATPTR(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
+ u16 maxpacket = GET_FLATPTR(pipe->pipe.maxpacket); int tdpos = 0; while (datasize) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; diff --git a/src/usb.c b/src/usb.c index 69231d5..aaa2c8e 100644 --- a/src/usb.c +++ b/src/usb.c @@ -140,19 +140,6 @@ usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev pipe->speed = usbdev->speed; pipe->maxpacket = epdesc->wMaxPacketSize; pipe->eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - struct usbdevice_s *hubdev = usbdev->hub->usbdev; - if (hubdev) { - if (hubdev->defpipe->speed == USB_HIGHSPEED) { - pipe->tt_devaddr = usbdev->devaddr; - pipe->tt_port = usbdev->port; - } else { - pipe->tt_devaddr = hubdev->defpipe->tt_devaddr; - pipe->tt_port = hubdev->defpipe->tt_port; - } - } else { - pipe->tt_devaddr = pipe->tt_port = 0; - } }
// Find the exponential period of the requested interrupt end point. diff --git a/src/usb.h b/src/usb.h index 72f2a7c..2c961e6 100644 --- a/src/usb.h +++ b/src/usb.h @@ -15,8 +15,6 @@ struct usb_pipe { u8 devaddr; u8 speed; u16 maxpacket; - u8 tt_devaddr; - u8 tt_port; u8 eptype; };
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ohci.c | 32 ++++++++++++++++++-------------- 1 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/usb-ohci.c b/src/usb-ohci.c index a0937a2..9980a8e 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -302,6 +302,17 @@ ohci_init(struct pci_device *pci, int busid) * End point communication ****************************************************************/
+// Setup fields in ed +static void +ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev + , struct usb_endpoint_descriptor *epdesc) +{ + usb_desc2pipe(&pipe->pipe, usbdev, epdesc); + pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7) + | (epdesc->wMaxPacketSize << 16) + | (usbdev->speed ? ED_LOWSPEED : 0)); +} + static struct usb_pipe * ohci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) @@ -323,9 +334,8 @@ ohci_alloc_intr_pipe(struct usbdevice_s *usbdev if (!pipe || !tds || !data) goto err; memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7); + ohci_desc2pipe(pipe, usbdev, epdesc); + pipe->ed.hwINFO &= ~ED_SKIP; pipe->data = data; pipe->count = count; pipe->tds = tds; @@ -333,7 +343,6 @@ ohci_alloc_intr_pipe(struct usbdevice_s *usbdev struct ohci_ed *ed = &pipe->ed; ed->hwHeadP = (u32)&tds[0]; ed->hwTailP = (u32)&tds[count-1]; - ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
int i; for (i=0; i<count-1; i++) { @@ -387,7 +396,8 @@ ohci_alloc_pipe(struct usbdevice_s *usbdev struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); if (usbpipe) { // Use previously allocated pipe. - usb_desc2pipe(usbpipe, usbdev, epdesc); + struct ohci_pipe *pipe = container_of(usbpipe, struct ohci_pipe, pipe); + ohci_desc2pipe(pipe, usbdev, epdesc); return usbpipe; }
@@ -398,8 +408,7 @@ ohci_alloc_pipe(struct usbdevice_s *usbdev return NULL; } memset(pipe, 0, sizeof(*pipe)); - usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - pipe->ed.hwINFO = ED_SKIP; + ohci_desc2pipe(pipe, usbdev, epdesc);
// Add queue head to controller list. pipe->ed.hwNextED = cntl->regs->ed_controlhead; @@ -439,9 +448,6 @@ ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); struct usb_ohci_s *cntl = container_of( pipe->pipe.cntl, struct usb_ohci_s, usb); - int maxpacket = pipe->pipe.maxpacket; - int lowspeed = pipe->pipe.speed; - int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
// Setup transfer descriptors struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3); @@ -469,16 +475,14 @@ ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize td++;
// Transfer data - pipe->ed.hwINFO = ED_SKIP; - barrier(); pipe->ed.hwHeadP = (u32)tds; pipe->ed.hwTailP = (u32)td; barrier(); - pipe->ed.hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0); + pipe->ed.hwINFO &= ~ED_SKIP; writel(&cntl->regs->cmdstatus, OHCI_CLF);
int ret = wait_ed(&pipe->ed); - pipe->ed.hwINFO = ED_SKIP; + pipe->ed.hwINFO |= ED_SKIP; if (ret) ohci_waittick(cntl); free(tds);
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ohci.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/usb-ohci.c b/src/usb-ohci.c index 9980a8e..b0d0365 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -353,16 +353,17 @@ ohci_alloc_intr_pipe(struct usbdevice_s *usbdev }
// Add to interrupt schedule. - barrier(); struct ohci_hcca *hcca = (void*)cntl->regs->hcca; if (frameexp == 0) { // Add to existing interrupt entry. struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; ed->hwNextED = intr_ed->hwNextED; + barrier(); intr_ed->hwNextED = (u32)ed; } else { int startpos = 1<<(frameexp-1); ed->hwNextED = hcca->int_table[startpos]; + barrier(); for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms) hcca->int_table[i] = (u32)ed; }
That flag is for qh.info2 - it being set in qh.info1 appears to be a typo.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index a99ac35..6494a3d 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -387,12 +387,10 @@ ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev { usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
- pipe->qh.info1 = ( - (1 << QH_MULT_SHIFT) - | (pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT) - | (pipe->pipe.speed << QH_SPEED_SHIFT) - | (pipe->pipe.ep << QH_EP_SHIFT) - | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT)); + pipe->qh.info1 = ((pipe->pipe.maxpacket << QH_MAXPACKET_SHIFT) + | (pipe->pipe.speed << QH_SPEED_SHIFT) + | (pipe->pipe.ep << QH_EP_SHIFT) + | (pipe->pipe.devaddr << QH_DEVADDR_SHIFT));
pipe->qh.info2 = (1 << QH_MULT_SHIFT); struct usbdevice_s *hubdev = usbdev->hub->usbdev;
Tested these patches on my AMD G-series/SB800 platform (Persimmon) and didn't have any problems. I was using a USB wireless keyboard and booting Ubuntu with a USB thumbdrive.
Dave
----- Original Message -----
From: "Kevin O'Connor" kevin@koconnor.net To: seabios@seabios.org Sent: Saturday, March 10, 2012 7:41:22 PM Subject: [SeaBIOS] [PATCH 00/19] USB improvements
This series updates the USB code. This is mostly a code reorganization, though there are a couple of bug fixes (mostly for OHCI).
-Kevin
Kevin O'Connor (19): Batch free USB pipes on OHCI controllers. Batch free USB pipes on UHCI controllers. Batch free USB pipes on EHCI controllers. usb: Centralize pipe free list code. usb: Remove cntl->defaultpipe cache. usb: Obtain free list items in main code. usb: Introduce 'struct usbdevice_s' to describe info for a given device. usb: Push 'struct usbdevice_s' usage through to pipe allocation. usb: Build path via chain of usbdevice_s. usb: Pass usbdevice_s to alloc_async_pipe. usb: Pass 'struct usbdevice_s' into controller alloc_async functions. usb: Pass 'struct usbdevice_s' to controller alloc_intr_pipe functions. usb: Move code around in usb controller code. usb: Generalize controller alloc_async_pipe / alloc_intr_pipe code. usb: Move code around in usb.c. usb: Move EHCI tt_* fields to EHCI controller code. usb: Populate OHCI endpoint descriptor info at pipe allocation. usb: Fix barrier() placement in OHCI interrupt schedule add. usb: Remove QH_MULT_SHIFT flag from qh.info1.
src/boot.c | 25 ++-- src/boot.h | 3 +- src/usb-ehci.c | 441 +++++++++++++++++++++++++++----------------------------- src/usb-ehci.h | 8 +- src/usb-hid.c | 28 ++-- src/usb-hid.h | 6 +- src/usb-hub.c | 14 +- src/usb-hub.h | 4 +- src/usb-msc.c | 14 +- src/usb-msc.h | 6 +- src/usb-ohci.c | 323 +++++++++++++++++++++--------------------- src/usb-ohci.h | 8 +- src/usb-uhci.c | 411 +++++++++++++++++++++++++--------------------------- src/usb-uhci.h | 8 +- src/usb.c | 277 +++++++++++++++++------------------ src/usb.h | 48 ++++--- 16 files changed, 797 insertions(+), 827 deletions(-)
-- 1.7.6.5
SeaBIOS mailing list SeaBIOS@seabios.org http://www.seabios.org/mailman/listinfo/seabios
On Wed, Mar 14, 2012 at 07:36:53AM -0600, Dave Frodin wrote:
Tested these patches on my AMD G-series/SB800 platform (Persimmon) and didn't have any problems. I was using a USB wireless keyboard and booting Ubuntu with a USB thumbdrive.
Thanks!
-Kevin