aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2015-02-09 23:50:35 +0000
committerMichael Brown <mcb30@ipxe.org>2015-02-10 01:14:22 +0000
commit17aceb34da3bad166cab8579a3616806fff8e05b (patch)
treeb5a155eb8dcd66bb06955601bd76b86e27730b23 /src/drivers
parentcf153f60a54b4706225f6326dc65b9343148c9f3 (diff)
downloadipxe-17aceb34da3bad166cab8579a3616806fff8e05b.tar.gz
[usb] Parse endpoint descriptor bInterval field
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/bus/usb.c27
-rw-r--r--src/drivers/usb/xhci.c10
-rw-r--r--src/drivers/usb/xhci.h5
3 files changed, 38 insertions, 4 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c
index 97c2e3fc..5a338a5e 100644
--- a/src/drivers/bus/usb.c
+++ b/src/drivers/bus/usb.c
@@ -227,10 +227,13 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
struct usb_configuration_descriptor *config,
struct usb_interface_descriptor *interface,
unsigned int type, unsigned int index ) {
+ struct usb_device *usb = ep->usb;
+ struct usb_port *port = usb->port;
struct usb_endpoint_descriptor *desc;
struct usb_endpoint_companion_descriptor *descx;
unsigned int sizes;
unsigned int burst;
+ unsigned int interval;
size_t mtu;
/* Locate endpoint descriptor */
@@ -246,9 +249,23 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
mtu = USB_ENDPOINT_MTU ( sizes );
burst = ( descx ? descx->burst : USB_ENDPOINT_BURST ( sizes ) );
+ /* Calculate interval */
+ if ( type == USB_INTERRUPT ) {
+ if ( port->speed >= USB_SPEED_HIGH ) {
+ /* 2^(desc->interval-1) is a microframe count */
+ interval = ( 1 << ( desc->interval - 1 ) );
+ } else {
+ /* desc->interval is a (whole) frame count */
+ interval = ( desc->interval << 3 );
+ }
+ } else {
+ /* desc->interval is a microframe count */
+ interval = desc->interval;
+ }
+
/* Describe endpoint */
usb_endpoint_describe ( ep, desc->endpoint, desc->attributes,
- mtu, burst );
+ mtu, burst, interval );
return 0;
}
@@ -286,8 +303,9 @@ int usb_endpoint_open ( struct usb_endpoint *ep ) {
}
ep->open = 1;
- DBGC2 ( usb, "USB %s %s opened with MTU %zd (burst %d)\n", usb->name,
- usb_endpoint_name ( ep->address ), ep->mtu, ep->burst );
+ DBGC2 ( usb, "USB %s %s opened with MTU %zd, burst %d, interval %d\n",
+ usb->name, usb_endpoint_name ( ep->address ), ep->mtu,
+ ep->burst, ep->interval );
return 0;
ep->open = 0;
@@ -1147,7 +1165,8 @@ static int register_usb ( struct usb_device *usb ) {
/* Describe control endpoint */
mtu = USB_EP0_DEFAULT_MTU ( port->speed );
usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
- USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST );
+ USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
+ USB_EP0_INTERVAL );
/* Open control endpoint */
if ( ( rc = usb_endpoint_open ( &usb->control ) ) != 0 )
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index cdebc47d..49901275 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -1986,6 +1986,7 @@ static void xhci_configure_endpoint_input ( struct xhci_device *xhci,
/* Populate endpoint context */
ep_ctx = ( input + xhci_input_context_offset ( xhci, endpoint->ctx ) );
+ ep_ctx->interval = endpoint->interval;
ep_ctx->type = endpoint->type;
ep_ctx->burst = endpoint->ep->burst;
ep_ctx->mtu = cpu_to_le16 ( endpoint->ep->mtu );
@@ -2252,6 +2253,7 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
struct xhci_endpoint *endpoint;
unsigned int ctx;
unsigned int type;
+ unsigned int interval;
int rc;
/* Calculate context index */
@@ -2265,6 +2267,13 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
if ( ep->address & USB_DIR_IN )
type |= XHCI_EP_TYPE_IN;
+ /* Calculate interval */
+ if ( type & XHCI_EP_TYPE_PERIODIC ) {
+ interval = ( fls ( ep->interval ) - 1 );
+ } else {
+ interval = ep->interval;
+ }
+
/* Allocate and initialise structure */
endpoint = zalloc ( sizeof ( *endpoint ) );
if ( ! endpoint ) {
@@ -2278,6 +2287,7 @@ static int xhci_endpoint_open ( struct usb_endpoint *ep ) {
endpoint->ep = ep;
endpoint->ctx = ctx;
endpoint->type = type;
+ endpoint->interval = interval;
endpoint->context = ( ( ( void * ) slot->context ) +
xhci_device_context_offset ( xhci, ctx ) );
diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h
index 7f768aa0..186ff27d 100644
--- a/src/drivers/usb/xhci.h
+++ b/src/drivers/usb/xhci.h
@@ -806,6 +806,9 @@ enum xhci_endpoint_state {
/** Input endpoint type */
#define XHCI_EP_TYPE_IN XHCI_EP_TYPE ( 4 )
+/** Periodic endpoint type */
+#define XHCI_EP_TYPE_PERIODIC XHCI_EP_TYPE ( 1 )
+
/** Endpoint dequeue cycle state */
#define XHCI_EP_DCS 0x00000001UL
@@ -1078,6 +1081,8 @@ struct xhci_endpoint {
unsigned int ctx;
/** Endpoint type */
unsigned int type;
+ /** Endpoint interval */
+ unsigned int interval;
/** Endpoint context */
struct xhci_endpoint_context *context;
/** Transfer ring */