Some results can be found here: http://dpaste.com/876523/
Before this patch I got a timeout at Inquiry.
Signed-off-by: Christian Gmeiner christian.gmeiner@gmail.com --- src/usb-ehci.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 2676615..0b71935 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -173,6 +173,34 @@ check_ehci_ports(struct usb_ehci_s *cntl) return hub.devcount; }
+static int ehci_set_async_schedule(struct usb_ehci_s *ehcic, int enable) +{ + dprintf(7, "%s: enable %d\n", __func__, enable); + + // Set async schedule status. + u32 cmd = readl(&ehcic->regs->usbcmd); + if (enable) + cmd |= CMD_ASE; + else + cmd &= ~CMD_ASE; + + writel(&ehcic->regs->usbcmd, cmd); + + /* Wait for the controller to accept async schedule status. + * This shouldn't take too long, but we should timeout nevertheless. + */ + enable = enable ? STS_ASS : 0; + int timeout = 100; /* time out after 100ms */ + while (((readl(&ehcic->regs->usbsts) & STS_ASS) != enable) + && timeout--) + mdelay(1); + if (timeout < 0) { + dprintf(7, "ehci async schedule status change timed out.\n"); + return 1; + } + return 0; +} +
/**************************************************************** * Setup @@ -410,6 +438,8 @@ ehci_desc2pipe(struct ehci_pipe *pipe, struct usbdevice_s *usbdev | QH_TOGGLECONTROL); else if (eptype == USB_ENDPOINT_XFER_INT) pipe->qh.info2 |= (0x01 << QH_SMASK_SHIFT) | (0x1c << QH_CMASK_SHIFT); + else if (eptype == USB_ENDPOINT_XFER_BULK) + pipe->qh.info1 |= QH_TOGGLECONTROL; }
static struct usb_pipe * @@ -561,6 +591,9 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) static int fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes) { + dprintf(1, "%s\t", __func__); + hexdump(buf, bytes); + u32 dest = (u32)buf; u32 *pos = td->buf; while (bytes) { @@ -649,9 +682,19 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) if (! CONFIG_USB_EHCI) return -1; struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); - dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" + dprintf(1, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" , &pipe->qh, dir, data, datasize);
+ dprintf(1, "data:"); + hexdump(data, datasize); + + + struct usb_ehci_s *ehcic = container_of( + GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb); + + // stop async schedule + ehci_set_async_schedule(ehcic, 0); + // 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); @@ -661,12 +704,17 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); int tdpos = 0; + struct ehci_qtd *last = &tds[0]; + int num = 0; + int chgm; + while (datasize) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; +/* int ret = ehci_wait_td(pipe, td, 5000); if (ret) return -1; - +*/ struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) , &tds[tdpos % STACKQTDS]);
@@ -677,9 +725,29 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
+ /* dump td buf */ + dprintf(1, "td #%d buf\t", num); + for (chgm = 0; chgm < ARRAY_SIZE(td->buf); chgm++) { + dprintf(1, "\tpointer %d: 0x%08x\n", chgm, td->buf[chgm]); + + if (td->buf[chgm] != 0) { + hexdump((const void *)td->buf[chgm], transfer); + } + } + data += transfer; datasize -= transfer; + num++; } + + dprintf(1, "ehci_send_bulk needs %d td's\n", num); + + /* update based on endpoint toggle */ + tds[0].token |= (pipe->pipe.toogle?QTD_TOGGLE:0); + pipe->qh.token|= (pipe->pipe.toogle?QTD_TOGGLE:0); + + ehci_set_async_schedule(ehcic, 1); + int i; for (i=0; i<STACKQTDS; i++) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; @@ -688,6 +756,11 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) return -1; }
+ ehci_set_async_schedule(ehcic, 0); + + /* update endpoint toggle based on device */ + pipe->pipe.toogle = (last->token & QTD_TOGGLE) >> 31; + return 0; }