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) {