From: Kevin O'Connor Date: Wed, 31 Dec 2014 06:55:48 +0000 (-0500) Subject: ohci: Merge ohci_send_control with ohci_send_bulk X-Git-Tag: rel-1.8.0~12 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=5372a3f7c8ceec09f7ebeb2545bfff7f38840084;p=seabios.git ohci: Merge ohci_send_control with ohci_send_bulk 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 --- diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c index ee31b83..11fe9fa 100644 --- a/src/hw/usb-ohci.c +++ b/src/hw/usb-ohci.c @@ -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; diff --git a/src/hw/usb-ohci.h b/src/hw/usb-ohci.h index db935ca..3dbc0e0 100644 --- a/src/hw/usb-ohci.h +++ b/src/hw/usb-ohci.h @@ -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); diff --git a/src/hw/usb.c b/src/hw/usb.c index ed2db8a..9e6cfc8 100644 --- a/src/hw/usb.c +++ b/src/hw/usb.c @@ -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: