}
struct usb_pipe *
-ehci_alloc_async_pipe(struct usb_pipe *dummy)
+ehci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc)
{
if (! CONFIG_USB_EHCI)
return NULL;
struct usb_ehci_s *cntl = container_of(
- dummy->cntl, struct usb_ehci_s, usb);
- dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
+ usbdev->hub->cntl, struct usb_ehci_s, usb);
+ u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
+
+ struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+ if (usbpipe) {
+ // Use previously allocated pipe.
+ usb_desc2pipe(usbpipe, usbdev, epdesc);
+ return usbpipe;
+ }
// Allocate a new queue head.
struct ehci_pipe *pipe;
- if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
+ if (eptype == USB_ENDPOINT_XFER_CONTROL)
pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
else
pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
return NULL;
}
memset(pipe, 0, sizeof(*pipe));
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
+ usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;
// Add queue head to controller list.
// usb-ehci.c
int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *ehci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc);
struct usb_pipe;
-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);
int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
}
struct usb_pipe *
-ohci_alloc_async_pipe(struct usb_pipe *dummy)
+ohci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc)
{
if (! CONFIG_USB_OHCI)
return NULL;
- if (dummy->eptype != USB_ENDPOINT_XFER_CONTROL) {
+ u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ if (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);
+ usbdev->hub->cntl, struct usb_ohci_s, usb);
dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
+ struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+ if (usbpipe) {
+ // Use previously allocated pipe.
+ usb_desc2pipe(usbpipe, usbdev, epdesc);
+ return usbpipe;
+ }
+
// Allocate a new queue head.
struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
if (!pipe) {
return NULL;
}
memset(pipe, 0, sizeof(*pipe));
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
+ usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
pipe->ed.hwINFO = ED_SKIP;
// Add queue head to controller list.
// usb-ohci.c
void ohci_init(struct pci_device *pci, int busid);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *ohci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc);
struct usb_pipe;
-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);
int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
}
struct usb_pipe *
-uhci_alloc_async_pipe(struct usb_pipe *dummy)
+uhci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc)
{
if (! CONFIG_USB_UHCI)
return NULL;
struct usb_uhci_s *cntl = container_of(
- dummy->cntl, struct usb_uhci_s, usb);
- dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
+ usbdev->hub->cntl, struct usb_uhci_s, usb);
+ u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+ dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);
+
+ struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
+ if (usbpipe) {
+ // Use previously allocated pipe.
+ usb_desc2pipe(usbpipe, usbdev, epdesc);
+ return usbpipe;
+ }
// Allocate a new queue head.
struct uhci_pipe *pipe;
- if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
+ if (eptype == USB_ENDPOINT_XFER_CONTROL)
pipe = malloc_tmphigh(sizeof(*pipe));
else
pipe = malloc_low(sizeof(*pipe));
return NULL;
}
memset(pipe, 0, sizeof(*pipe));
- memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
+ usb_desc2pipe(&pipe->pipe, usbdev, epdesc);
pipe->qh.element = UHCI_PTR_TERM;
pipe->iobase = cntl->iobase;
pipe->qh.link = control_qh->link;
barrier();
control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
- if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL)
+ if (eptype == USB_ENDPOINT_XFER_CONTROL)
cntl->control_qh = &pipe->qh;
return &pipe->pipe;
}
// usb-uhci.c
void uhci_init(struct pci_device *pci, int busid);
+struct usbdevice_s;
+struct usb_endpoint_descriptor;
+struct usb_pipe *uhci_alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc);
struct usb_pipe;
-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);
int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize);
}
// Fill "pipe" endpoint info from an endpoint descriptor.
-static void
-desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
- , struct usb_endpoint_descriptor *epdesc)
+void
+usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc)
{
- memset(pipe, 0, sizeof(*pipe));
pipe->cntl = usbdev->hub->cntl;
pipe->type = usbdev->hub->cntl->type;
pipe->ep = epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
}
}
-// Allocate an async pipe (control or bulk).
+// Check for an available pipe on the freelist.
struct usb_pipe *
-alloc_async_pipe(struct usbdevice_s *usbdev
- , struct usb_endpoint_descriptor *epdesc)
+usb_getFreePipe(struct usb_s *cntl, u8 eptype)
{
- struct usb_pipe dummy;
- desc2pipe(&dummy, usbdev, epdesc);
-
- // Check for an available pipe on the freelist.
- struct usb_pipe **pfree = &dummy.cntl->freelist;
+ struct usb_pipe **pfree = &cntl->freelist;
for (;;) {
struct usb_pipe *pipe = *pfree;
if (!pipe)
- break;
- if (pipe->eptype == dummy.eptype) {
- // Use previously allocated pipe.
+ return NULL;
+ if (pipe->eptype == eptype) {
*pfree = pipe->freenext;
- memcpy(pipe, &dummy, sizeof(*pipe));
return pipe;
}
pfree = &pipe->freenext;
}
+}
- // Allocate a new pipe.
- switch (dummy.type) {
+// Allocate an async pipe (control or bulk).
+struct usb_pipe *
+alloc_async_pipe(struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc)
+{
+ switch (usbdev->hub->cntl->type) {
default:
case USB_TYPE_UHCI:
- return uhci_alloc_async_pipe(&dummy);
+ return uhci_alloc_async_pipe(usbdev, epdesc);
case USB_TYPE_OHCI:
- return ohci_alloc_async_pipe(&dummy);
+ return ohci_alloc_async_pipe(usbdev, epdesc);
case USB_TYPE_EHCI:
- return ehci_alloc_async_pipe(&dummy);
+ return ehci_alloc_async_pipe(usbdev, epdesc);
}
}
, struct usb_endpoint_descriptor *epdesc)
{
struct usb_pipe dummy;
- desc2pipe(&dummy, usbdev, epdesc);
+ usb_desc2pipe(&dummy, usbdev, epdesc);
// Find the exponential period of the requested time.
int period = epdesc->bInterval;
int frameexp;
, void *data);
int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize);
void free_pipe(struct usb_pipe *pipe);
+void usb_desc2pipe(struct usb_pipe *pipe, struct usbdevice_s *usbdev
+ , struct usb_endpoint_descriptor *epdesc);
+struct usb_pipe *usb_getFreePipe(struct usb_s *cntl, u8 eptype);
struct usb_pipe *alloc_async_pipe(struct usbdevice_s *usbdev
, struct usb_endpoint_descriptor *epdesc);
struct usb_pipe *alloc_intr_pipe(struct usbdevice_s *usbdev