[SeaBIOS] [PATCH RFC] Quite hacky patch to get USB ehci working on bare metal.
Christian Gmeiner
christian.gmeiner at gmail.com
Mon Jan 14 16:55:33 CET 2013
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 at 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;
}
--
1.7.12.2.421.g261b511
More information about the SeaBIOS
mailing list