struct ehci_qtd *next_td, *tds;
void *data;
struct usb_pipe pipe;
- u8 iscontrol;
};
return 0;
}
-static struct usb_pipe *
-ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
+struct usb_pipe *
+ehci_alloc_async_pipe(struct usb_pipe *dummy)
{
if (! CONFIG_USB_EHCI)
return NULL;
struct usb_ehci_s *cntl = container_of(
dummy->cntl, struct usb_ehci_s, usb);
- dprintf(7, "ehci_alloc_pipe %p %d\n", &cntl->usb, iscontrol);
-
- struct usb_pipe *freepipe = cntl->usb.freelist;
- while (freepipe) {
- struct ehci_pipe *pipe = container_of(cntl->usb.freelist
- , struct ehci_pipe, pipe);
- if (pipe->iscontrol == iscontrol) {
- // Use previously allocated queue head.
- cntl->usb.freelist = pipe->pipe.freenext;
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
- return &pipe->pipe;
- }
- freepipe = freepipe->freenext;
- }
+ dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
// Allocate a new queue head.
struct ehci_pipe *pipe;
- if (iscontrol)
+ if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
else
pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
memset(pipe, 0, sizeof(*pipe));
memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
- pipe->iscontrol = iscontrol;
// Add queue head to controller list.
struct ehci_qh *async_qh = cntl->async_qh;
return &pipe->pipe;
}
-struct usb_pipe *
-ehci_alloc_control_pipe(struct usb_pipe *dummy)
-{
- return ehci_alloc_pipe(dummy, 1);
-}
-
-struct usb_pipe *
-ehci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
- return ehci_alloc_pipe(dummy, 0);
-}
-
static int
fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes)
{
// usb-ehci.c
int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci);
struct usb_pipe;
-struct usb_pipe *ehci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *ehci_alloc_async_pipe(struct usb_pipe *dummy);
int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
, void *data, int datasize);
-struct usb_pipe *ehci_alloc_bulk_pipe(struct usb_pipe *dummy);
int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
struct usb_pipe *ehci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
int ehci_poll_intr(struct usb_pipe *p, void *data);
}
struct usb_pipe *
-ohci_alloc_control_pipe(struct usb_pipe *dummy)
+ohci_alloc_async_pipe(struct usb_pipe *dummy)
{
if (! CONFIG_USB_OHCI)
return NULL;
+ if (dummy->eptype != USB_ENDPOINT_XFER_CONTROL) {
+ dprintf(1, "OHCI Bulk transfers not supported.\n");
+ return NULL;
+ }
struct usb_ohci_s *cntl = container_of(
dummy->cntl, struct usb_ohci_s, usb);
- dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb);
-
- if (cntl->usb.freelist) {
- // Use previously allocated queue head.
- struct ohci_pipe *pipe = container_of(cntl->usb.freelist
- , struct ohci_pipe, pipe);
- cntl->usb.freelist = pipe->pipe.freenext;
-
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
- return &pipe->pipe;
- }
+ dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
// Allocate a new queue head.
struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
return ret;
}
-struct usb_pipe *
-ohci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
- if (! CONFIG_USB_OHCI)
- return NULL;
- dprintf(1, "OHCI Bulk transfers not supported.\n");
- return NULL;
-}
-
int
ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
{
// usb-ohci.c
void ohci_init(struct pci_device *pci, int busid);
struct usb_pipe;
-struct usb_pipe *ohci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *ohci_alloc_async_pipe(struct usb_pipe *dummy);
int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
, void *data, int datasize);
-struct usb_pipe *ohci_alloc_bulk_pipe(struct usb_pipe *dummy);
int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
struct usb_pipe *ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
int ohci_poll_intr(struct usb_pipe *p, void *data);
struct usb_pipe pipe;
u16 iobase;
u8 toggle;
- u8 iscontrol;
};
}
}
-static struct usb_pipe *
-uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol)
+struct usb_pipe *
+uhci_alloc_async_pipe(struct usb_pipe *dummy)
{
if (! CONFIG_USB_UHCI)
return NULL;
struct usb_uhci_s *cntl = container_of(
dummy->cntl, struct usb_uhci_s, usb);
- dprintf(7, "uhci_alloc_pipe %p %d\n", &cntl->usb, iscontrol);
-
- struct usb_pipe *freepipe = cntl->usb.freelist;
- while (freepipe) {
- struct uhci_pipe *pipe = container_of(cntl->usb.freelist
- , struct uhci_pipe, pipe);
- if (pipe->iscontrol == iscontrol) {
- // Use previously allocated queue head.
- cntl->usb.freelist = pipe->pipe.freenext;
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
- return &pipe->pipe;
- }
- freepipe = freepipe->freenext;
- }
+ dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
// Allocate a new queue head.
struct uhci_pipe *pipe;
- if (iscontrol)
+ if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
pipe = malloc_tmphigh(sizeof(*pipe));
else
pipe = malloc_low(sizeof(*pipe));
memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
pipe->qh.element = UHCI_PTR_TERM;
pipe->iobase = cntl->iobase;
- pipe->iscontrol = iscontrol;
// Add queue head to controller list.
struct uhci_qh *control_qh = cntl->control_qh;
pipe->qh.link = control_qh->link;
barrier();
control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
- if (iscontrol)
+ if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
cntl->control_qh = &pipe->qh;
return &pipe->pipe;
}
-struct usb_pipe *
-uhci_alloc_control_pipe(struct usb_pipe *dummy)
-{
- return uhci_alloc_pipe(dummy, 1);
-}
-
-struct usb_pipe *
-uhci_alloc_bulk_pipe(struct usb_pipe *dummy)
-{
- return uhci_alloc_pipe(dummy, 0);
-}
-
int
uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
, void *data, int datasize)
// usb-uhci.c
void uhci_init(struct pci_device *pci, int busid);
struct usb_pipe;
-struct usb_pipe *uhci_alloc_control_pipe(struct usb_pipe *dummy);
+struct usb_pipe *uhci_alloc_async_pipe(struct usb_pipe *dummy);
int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
, void *data, int datasize);
-struct usb_pipe *uhci_alloc_bulk_pipe(struct usb_pipe *dummy);
int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
struct usb_pipe *uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp);
int uhci_poll_intr(struct usb_pipe *p, void *data);
cntl->freelist = pipe;
}
-// Allocate a control pipe to a default endpoint (which can only be
-// used by 32bit code)
+// Allocate an async pipe (control or bulk).
static struct usb_pipe *
-alloc_default_control_pipe(struct usb_pipe *dummy)
+alloc_async_pipe(struct usb_pipe *dummy)
{
+ // Check for an available pipe on the freelist.
+ struct usb_pipe **pfree = &dummy->cntl->freelist;
+ for (;;) {
+ struct usb_pipe *pipe = *pfree;
+ if (!pipe)
+ break;
+ if (pipe->eptype == dummy->eptype) {
+ // Use previously allocated pipe.
+ *pfree = pipe->freenext;
+ memcpy(pipe, dummy, sizeof(*pipe));
+ return pipe;
+ }
+ pfree = &pipe->freenext;
+ }
+
+ // Allocate a new pipe.
switch (dummy->type) {
default:
case USB_TYPE_UHCI:
- return uhci_alloc_control_pipe(dummy);
+ return uhci_alloc_async_pipe(dummy);
case USB_TYPE_OHCI:
- return ohci_alloc_control_pipe(dummy);
+ return ohci_alloc_async_pipe(dummy);
case USB_TYPE_EHCI:
- return ehci_alloc_control_pipe(dummy);
+ return ehci_alloc_async_pipe(dummy);
}
}
{
struct usb_pipe dummy;
desc2pipe(&dummy, pipe, epdesc);
- switch (pipe->type) {
- default:
- case USB_TYPE_UHCI:
- return uhci_alloc_bulk_pipe(&dummy);
- case USB_TYPE_OHCI:
- return ohci_alloc_bulk_pipe(&dummy);
- case USB_TYPE_EHCI:
- return ehci_alloc_bulk_pipe(&dummy);
- }
+ dummy.eptype = USB_ENDPOINT_XFER_BULK;
+ return alloc_async_pipe(&dummy);
}
int
dummy.type = cntl->type;
dummy.maxpacket = 8;
dummy.path = (u64)-1;
- struct usb_pipe *defpipe = alloc_default_control_pipe(&dummy);
+ dummy.eptype = USB_ENDPOINT_XFER_CONTROL;
+ struct usb_pipe *defpipe = alloc_async_pipe(&dummy);
if (!defpipe)
return NULL;
defpipe->speed = speed;
u16 maxpacket;
u8 tt_devaddr;
u8 tt_port;
+ u8 eptype;
};
// Common information for usb controllers.