aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-12-30 21:16:04 -0500
committerKevin O'Connor <kevin@koconnor.net>2015-01-07 10:13:46 -0500
commitabd674200825ef0df1cb8560b774e24db01cb9f2 (patch)
treed849d23ce42abacd1005fce0712de48400d9773c
parent1bd976b7befb7d65cbfa778ba2eb03e30cb76068 (diff)
downloadseabios-abd674200825ef0df1cb8560b774e24db01cb9f2.zip
seabios-abd674200825ef0df1cb8560b774e24db01cb9f2.tar.gz
seabios-abd674200825ef0df1cb8560b774e24db01cb9f2.tar.bz2
ehci: Merge ehci_send_control with ehci_send_bulk
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>
-rw-r--r--src/hw/usb-ehci.c96
-rw-r--r--src/hw/usb-ehci.h5
-rw-r--r--src/hw/usb.c4
3 files changed, 34 insertions, 71 deletions
diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c
index 22e58a4..a738316 100644
--- a/src/hw/usb-ehci.c
+++ b/src/hw/usb-ehci.c
@@ -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 4 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;
diff --git a/src/hw/usb-ehci.h b/src/hw/usb-ehci.h
index da74438..08ae046 100644
--- a/src/hw/usb-ehci.h
+++ b/src/hw/usb-ehci.h
@@ -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);
diff --git a/src/hw/usb.c b/src/hw/usb.c
index 75412f9..ed2db8a 100644
--- a/src/hw/usb.c
+++ b/src/hw/usb.c
@@ -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;