]> xenbits.xensource.com Git - people/andrewcoop/seabios.git/commitdiff
ehci: Merge ehci_send_control with ehci_send_bulk
authorKevin O'Connor <kevin@koconnor.net>
Wed, 31 Dec 2014 02:16:04 +0000 (21:16 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 7 Jan 2015 15:13:46 +0000 (10:13 -0500)
Merge both the control and bulk pipe sending functions into one new
function: ehci_send_pipe().  The two existing functions were similar,
and by merging them the resulting code supports more flexible control
transfers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/hw/usb-ehci.c
src/hw/usb-ehci.h
src/hw/usb.c

index 22e58a4ecad0103b8691c92cca5c47958de86f7c..a7383166dfdf0fdf65d05edf19fc8b77cef67e99 100644 (file)
@@ -539,87 +539,39 @@ ehci_fill_tdbuf(struct ehci_qtd *td, u32 dest, int transfer)
         *pos++ = dest;
 }
 
-int
-ehci_send_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                  , void *data, int datasize)
-{
-    ASSERT32FLAT();
-    if (! CONFIG_USB_EHCI)
-        return -1;
-    dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n"
-            , p, dir, cmdsize, datasize);
-    if (datasize > 4*4096 || cmdsize > 4*4096) {
-        // XXX - should support larger sizes.
-        warn_noalloc();
-        return -1;
-    }
-    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
-
-    // Setup transfer descriptors
-    struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3);
-    if (!tds) {
-        warn_noalloc();
-        return -1;
-    }
-    memset(tds, 0, sizeof(*tds) * 3);
-    struct ehci_qtd *td = tds;
-
-    td->qtd_next = (u32)&td[1];
-    td->alt_next = EHCI_PTR_TERM;
-    td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE
-                 | QTD_PID_SETUP | ehci_maxerr(3));
-    ehci_fill_tdbuf(td, (u32)cmd, cmdsize);
-    td++;
-
-    if (datasize) {
-        td->qtd_next = (u32)&td[1];
-        td->alt_next = EHCI_PTR_TERM;
-        td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE
-                     | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
-        ehci_fill_tdbuf(td, (u32)data, datasize);
-        td++;
-    }
-
-    td->qtd_next = EHCI_PTR_TERM;
-    td->alt_next = EHCI_PTR_TERM;
-    td->token = (QTD_TOGGLE | QTD_STS_ACTIVE
-                 | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3));
-
-    // Transfer data
-    u32 end = timer_calc(usb_xfer_time(p, datasize));
-    barrier();
-    pipe->qh.qtd_next = (u32)tds;
-    int i, ret=0;
-    for (i=0; i<3; i++) {
-        struct ehci_qtd *td = &tds[i];
-        ret = ehci_wait_td(pipe, td, end);
-        if (ret)
-            break;
-    }
-    free(tds);
-    return ret;
-}
-
-#define STACKQTDS 4
+#define STACKQTDS 6
 
 int
-ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
+ehci_send_pipe(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+               , 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(7, "ehci_send_pipe qh=%p dir=%d data=%p size=%d\n"
             , &pipe->qh, dir, data, datasize);
 
-    // Allocate tds on stack (with required alignment)
+    // Allocate 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), *td = tds;
     memset(tds, 0, sizeof(*tds) * STACKQTDS);
 
     // Setup transfer descriptors
     u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket);
+    u32 toggle = 0;
+    if (cmd) {
+        // Send setup pid on control transfers
+        td->qtd_next = (u32)MAKE_FLATPTR(GET_SEG(SS), td+1);
+        td->alt_next = EHCI_PTR_TERM;
+        td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE
+                     | QTD_PID_SETUP | ehci_maxerr(3));
+        ehci_fill_tdbuf(td, (u32)cmd, cmdsize);
+        td++;
+        toggle = QTD_TOGGLE;
+    }
     u32 dest = (u32)data, dataend = dest + datasize;
     while (dest < dataend) {
+        // Send data pids
         if (td >= &tds[STACKQTDS]) {
             warn_noalloc();
             return -1;
@@ -630,12 +582,24 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
             transfer = ALIGN_DOWN(maxtransfer, maxpacket);
         td->qtd_next = (u32)MAKE_FLATPTR(GET_SEG(SS), td+1);
         td->alt_next = EHCI_PTR_TERM;
-        td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE
+        td->token = (ehci_explen(transfer) | toggle | QTD_STS_ACTIVE
                      | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
         ehci_fill_tdbuf(td, dest, transfer);
         td++;
         dest += transfer;
     }
+    if (cmd) {
+        // Send status pid on control transfers
+        if (td >= &tds[STACKQTDS]) {
+            warn_noalloc();
+            return -1;
+        }
+        td->qtd_next = EHCI_PTR_TERM;
+        td->alt_next = EHCI_PTR_TERM;
+        td->token = (QTD_TOGGLE | QTD_STS_ACTIVE
+                     | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3));
+        td++;
+    }
 
     // Transfer data
     (td-1)->qtd_next = EHCI_PTR_TERM;
index da74438f6749af4b188cff3d6192ecdfc4e52d7a..08ae0462f69a0f9f822301ace2349670fe811f5e 100644 (file)
@@ -9,9 +9,8 @@ struct usb_pipe;
 struct usb_pipe *ehci_realloc_pipe(struct usbdevice_s *usbdev
                                    , struct usb_pipe *upipe
                                    , struct usb_endpoint_descriptor *epdesc);
-int ehci_send_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);
+int ehci_send_pipe(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+                   , void *data, int datasize);
 int ehci_poll_intr(struct usb_pipe *p, void *data);
 
 
index 75412f91ae622707e03b22e07ddaae2e483208e9..ed2db8a22d38ee25ba926c3686ca6fffe3565322 100644 (file)
@@ -57,7 +57,7 @@ usb_send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize
     case USB_TYPE_OHCI:
         return ohci_send_control(pipe, dir, cmd, cmdsize, data, datasize);
     case USB_TYPE_EHCI:
-        return ehci_send_control(pipe, dir, cmd, cmdsize, data, datasize);
+        return ehci_send_pipe(pipe, dir, cmd, cmdsize, data, datasize);
     case USB_TYPE_XHCI:
         return xhci_send_control(pipe, dir, cmd, cmdsize, data, datasize);
     }
@@ -75,7 +75,7 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize)
             return -1;
         return ohci_send_bulk(pipe_fl, dir, data, datasize);
     case USB_TYPE_EHCI:
-        return ehci_send_bulk(pipe_fl, dir, data, datasize);
+        return ehci_send_pipe(pipe_fl, dir, NULL, 0, data, datasize);
     case USB_TYPE_XHCI:
         if (MODESEGMENT)
             return -1;