[SeaBIOS] [PATCH 1/9] ehci: No need to support td array wrapping

Kevin O'Connor kevin at koconnor.net
Thu Jan 1 01:57:22 CET 2015


The maximum bulk transfer is 64K and 4 QTDs can always transfer 64K.
So, there is no need to support a transfer with more than 4 QTDs.
Build the entire transaction and then submit it in one operation to
simplify the code.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/hw/usb-ehci.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c
index 8938915..feef4a1 100644
--- a/src/hw/usb-ehci.c
+++ b/src/hw/usb-ehci.c
@@ -626,37 +626,35 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
             , &pipe->qh, dir, data, datasize);
 
     // Allocate 4 tds on stack (with required alignment)
-    u32 end = timer_calc(usb_xfer_time(p, datasize));
     u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1];
-    struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN);
+    struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN), *td = tds;
     memset(tds, 0, sizeof(*tds) * STACKQTDS);
-    barrier();
-    SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
 
+    // Setup transfer descriptors
     u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
-    int tdpos = 0;
     while (datasize) {
-        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
-        int ret = ehci_wait_td(pipe, td, end);
-        if (ret)
+        if (td >= &tds[STACKQTDS]) {
+            warn_noalloc();
             return -1;
-
-        struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
-                                                 , &tds[tdpos % STACKQTDS]);
-
+        }
         int transfer = fillTDbuffer(td, maxpacket, data, datasize);
-        td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl);
+        td->qtd_next = (u32)MAKE_FLATPTR(GET_SEG(SS), td+1);
         td->alt_next = EHCI_PTR_TERM;
-        barrier();
         td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE
                      | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
+        td++;
 
         data += transfer;
         datasize -= transfer;
     }
+
+    // Transfer data
+    (td-1)->qtd_next = EHCI_PTR_TERM;
+    barrier();
+    SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
+    u32 end = timer_calc(usb_xfer_time(p, datasize));
     int i;
-    for (i=0; i<STACKQTDS; i++) {
-        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
+    for (i=0, td=tds; i<STACKQTDS; i++, td++) {
         int ret = ehci_wait_td(pipe, td, end);
         if (ret)
             return -1;
-- 
1.9.3




More information about the SeaBIOS mailing list