]> xenbits.xensource.com Git - seabios.git/commitdiff
ohci: Merge ohci_send_control with ohci_send_bulk
authorKevin O'Connor <kevin@koconnor.net>
Wed, 31 Dec 2014 06:55:48 +0000 (01:55 -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: ohci_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-ohci.c
src/hw/usb-ohci.h
src/hw/usb.c

index ee31b8361cbb0065f603da0dc420d928fca0c2ed..11fe9fadbe3d88cf41e8b5ed5b4038808f089624 100644 (file)
@@ -455,79 +455,37 @@ wait_ed(struct ohci_ed *ed, int timeout)
     }
 }
 
-int
-ohci_send_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                  , void *data, int datasize)
-{
-    if (! CONFIG_USB_OHCI)
-        return -1;
-    dprintf(5, "ohci_control %p\n", p);
-    if (datasize > 4096) {
-        // XXX - should support larger sizes.
-        warn_noalloc();
-        return -1;
-    }
-    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
-
-    // Setup transfer descriptors
-    struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
-    if (!tds) {
-        warn_noalloc();
-        return -1;
-    }
-    struct ohci_td *td = tds;
-    td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
-    td->hwCBP = (u32)cmd;
-    td->hwNextTD = (u32)&td[1];
-    td->hwBE = (u32)cmd + cmdsize - 1;
-    td++;
-    if (datasize) {
-        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
-        td->hwCBP = (u32)data;
-        td->hwNextTD = (u32)&td[1];
-        td->hwBE = (u32)data + datasize - 1;
-        td++;
-    }
-    td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
-    td->hwCBP = 0;
-    td->hwNextTD = (u32)&td[1];
-    td->hwBE = 0;
-    td++;
-
-    // Transfer data
-    pipe->ed.hwHeadP = (u32)tds;
-    pipe->ed.hwTailP = (u32)td;
-    barrier();
-    pipe->ed.hwINFO &= ~ED_SKIP;
-    writel(&pipe->regs->cmdstatus, OHCI_CLF);
-
-    int ret = wait_ed(&pipe->ed, usb_xfer_time(p, datasize));
-    pipe->ed.hwINFO |= ED_SKIP;
-    if (ret)
-        ohci_waittick(pipe->regs);
-    free(tds);
-    return ret;
-}
-
-#define STACKOTDS 16
+#define STACKOTDS 18
 #define OHCI_TD_ALIGN 16
 
 int
-ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
+ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+               , void *data, int datasize)
 {
     ASSERT32FLAT();
     if (! CONFIG_USB_OHCI)
         return -1;
-    dprintf(7, "ohci_send_bulk %p\n", p);
+    dprintf(7, "ohci_send_pipe %p\n", p);
     struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
 
-    // Allocate 16 tds on stack (with required alignment)
+    // Allocate tds on stack (with required alignment)
     u8 tdsbuf[sizeof(struct ohci_td) * STACKOTDS + OHCI_TD_ALIGN - 1];
     struct ohci_td *tds = (void*)ALIGN((u32)tdsbuf, OHCI_TD_ALIGN), *td = tds;
     memset(tds, 0, sizeof(*tds) * STACKOTDS);
 
     // Setup transfer descriptors
     u16 maxpacket = pipe->pipe.maxpacket;
+    u32 toggle = 0, statuscmd = OHCI_BLF;
+    if (cmd) {
+        // Send setup pid on control transfers
+        td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
+        td->hwCBP = (u32)cmd;
+        td->hwNextTD = (u32)&td[1];
+        td->hwBE = (u32)cmd + cmdsize - 1;
+        td++;
+        toggle = TD_T_DATA1;
+        statuscmd = OHCI_CLF;
+    }
     u32 dest = (u32)data, dataend = dest + datasize;
     while (dest < dataend) {
         // Send data pids
@@ -539,20 +497,32 @@ ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
         int transfer = dataend - dest;
         if (transfer > maxtransfer)
             transfer = ALIGN_DOWN(maxtransfer, maxpacket);
-        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_CC;
+        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | toggle | TD_CC;
         td->hwCBP = dest;
         td->hwNextTD = (u32)&td[1];
         td->hwBE = dest + transfer - 1;
         td++;
         dest += transfer;
     }
+    if (cmd) {
+        // Send status pid on control transfers
+        if (td >= &tds[STACKOTDS]) {
+            warn_noalloc();
+            return -1;
+        }
+        td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
+        td->hwCBP = 0;
+        td->hwNextTD = (u32)&td[1];
+        td->hwBE = 0;
+        td++;
+    }
 
     // Transfer data
     pipe->ed.hwHeadP = (u32)tds | (pipe->ed.hwHeadP & ED_C);
     pipe->ed.hwTailP = (u32)td;
     barrier();
     pipe->ed.hwINFO &= ~ED_SKIP;
-    writel(&pipe->regs->cmdstatus, OHCI_BLF);
+    writel(&pipe->regs->cmdstatus, statuscmd);
 
     int ret = wait_ed(&pipe->ed, usb_xfer_time(p, datasize));
     pipe->ed.hwINFO |= ED_SKIP;
index db935cab73f53aae86c4fc8dd0675a7fdf37e55e..3dbc0e098fea6e1cc62941d22e93c71b342428ef 100644 (file)
@@ -9,9 +9,8 @@ struct usb_pipe;
 struct usb_pipe *ohci_realloc_pipe(struct usbdevice_s *usbdev
                                    , struct usb_pipe *upipe
                                    , struct usb_endpoint_descriptor *epdesc);
-int ohci_send_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
-                      , void *data, int datasize);
-int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
+int ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
+                   , void *data, int datasize);
 int ohci_poll_intr(struct usb_pipe *p, void *data);
 
 
index ed2db8a22d38ee25ba926c3686ca6fffe3565322..9e6cfc87950a063dc7b03a98d9a3a3a5f2af6635 100644 (file)
@@ -55,7 +55,7 @@ usb_send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize
     case USB_TYPE_UHCI:
         return uhci_send_control(pipe, dir, cmd, cmdsize, data, datasize);
     case USB_TYPE_OHCI:
-        return ohci_send_control(pipe, dir, cmd, cmdsize, data, datasize);
+        return ohci_send_pipe(pipe, dir, cmd, cmdsize, data, datasize);
     case USB_TYPE_EHCI:
         return ehci_send_pipe(pipe, dir, cmd, cmdsize, data, datasize);
     case USB_TYPE_XHCI:
@@ -73,7 +73,7 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize)
     case USB_TYPE_OHCI:
         if (MODESEGMENT)
             return -1;
-        return ohci_send_bulk(pipe_fl, dir, data, datasize);
+        return ohci_send_pipe(pipe_fl, dir, NULL, 0, data, datasize);
     case USB_TYPE_EHCI:
         return ehci_send_pipe(pipe_fl, dir, NULL, 0, data, datasize);
     case USB_TYPE_XHCI: