mirror of https://github.com/ipxe/ipxe.git
[usb] Add clear_tt() hub method to clear transaction translator buffer
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/35/head
parent
de6f4e3ede
commit
9e88194655
|
@ -1022,7 +1022,7 @@ static void ehci_endpoint_close ( struct usb_endpoint *ep ) {
|
||||||
/* No way to prevent hardware from continuing to
|
/* No way to prevent hardware from continuing to
|
||||||
* access the memory, so leak it.
|
* access the memory, so leak it.
|
||||||
*/
|
*/
|
||||||
DBGC ( ehci, "EHCI %p %s endpoint %d could not unschedule: "
|
DBGC ( ehci, "EHCI %p %s endpoint %02x could not unschedule: "
|
||||||
"%s\n", ehci, usb->name, ep->address, strerror ( rc ) );
|
"%s\n", ehci, usb->name, ep->address, strerror ( rc ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1217,7 +1217,7 @@ static void ehci_endpoint_poll ( struct ehci_endpoint *endpoint ) {
|
||||||
*/
|
*/
|
||||||
if ( status & EHCI_STATUS_HALTED ) {
|
if ( status & EHCI_STATUS_HALTED ) {
|
||||||
rc = -EIO_STATUS ( status );
|
rc = -EIO_STATUS ( status );
|
||||||
DBGC ( ehci, "EHCI %p %s endpoint %d completion %d "
|
DBGC ( ehci, "EHCI %p %s endpoint %02x completion %d "
|
||||||
"failed (status %02x): %s\n", ehci, usb->name,
|
"failed (status %02x): %s\n", ehci, usb->name,
|
||||||
ep->address, index, status, strerror ( rc ) );
|
ep->address, index, status, strerror ( rc ) );
|
||||||
while ( ! iobuf )
|
while ( ! iobuf )
|
||||||
|
@ -1496,6 +1496,25 @@ static int ehci_hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear transaction translator buffer
|
||||||
|
*
|
||||||
|
* @v hub USB hub
|
||||||
|
* @v port USB port
|
||||||
|
* @v ep USB endpoint
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int ehci_hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
|
||||||
|
struct usb_endpoint *ep ) {
|
||||||
|
struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
|
||||||
|
|
||||||
|
/* Should never be called; this is a root hub */
|
||||||
|
DBGC ( ehci, "EHCI %p port %d nonsensical CLEAR_TT for %s endpoint "
|
||||||
|
"%02x\n", ehci, port->address, ep->usb->name, ep->address );
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll for port status changes
|
* Poll for port status changes
|
||||||
*
|
*
|
||||||
|
@ -1706,6 +1725,7 @@ static struct usb_host_operations ehci_operations = {
|
||||||
.enable = ehci_hub_enable,
|
.enable = ehci_hub_enable,
|
||||||
.disable = ehci_hub_disable,
|
.disable = ehci_hub_disable,
|
||||||
.speed = ehci_hub_speed,
|
.speed = ehci_hub_speed,
|
||||||
|
.clear_tt = ehci_hub_clear_tt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -338,6 +338,35 @@ static int hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear transaction translator buffer
|
||||||
|
*
|
||||||
|
* @v hub USB hub
|
||||||
|
* @v port USB port
|
||||||
|
* @v ep USB endpoint
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
|
||||||
|
struct usb_endpoint *ep ) {
|
||||||
|
struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
|
||||||
|
struct usb_device *usb = hubdev->usb;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Clear transaction translator buffer. All hubs must support
|
||||||
|
* single-TT operation; we simplify our code by supporting
|
||||||
|
* only this configuration.
|
||||||
|
*/
|
||||||
|
if ( ( rc = usb_hub_clear_tt_buffer ( usb, ep->usb->address,
|
||||||
|
ep->address, ep->attributes,
|
||||||
|
USB_HUB_TT_SINGLE ) ) != 0 ) {
|
||||||
|
DBGC ( hubdev, "HUB %s port %d could not clear TT buffer: %s\n",
|
||||||
|
hubdev->name, port->address, strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** USB hub operations */
|
/** USB hub operations */
|
||||||
static struct usb_hub_driver_operations hub_operations = {
|
static struct usb_hub_driver_operations hub_operations = {
|
||||||
.open = hub_open,
|
.open = hub_open,
|
||||||
|
@ -345,6 +374,7 @@ static struct usb_hub_driver_operations hub_operations = {
|
||||||
.enable = hub_enable,
|
.enable = hub_enable,
|
||||||
.disable = hub_disable,
|
.disable = hub_disable,
|
||||||
.speed = hub_speed,
|
.speed = hub_speed,
|
||||||
|
.clear_tt = hub_clear_tt,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -129,6 +129,11 @@ struct usb_hub_port_status {
|
||||||
( USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE | \
|
( USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE | \
|
||||||
USB_REQUEST_TYPE ( 12 ) )
|
USB_REQUEST_TYPE ( 12 ) )
|
||||||
|
|
||||||
|
/** Clear transaction translator buffer */
|
||||||
|
#define USB_HUB_CLEAR_TT_BUFFER \
|
||||||
|
( USB_DIR_OUT | USB_TYPE_CLASS | USB_HUB_RECIP_PORT | \
|
||||||
|
USB_REQUEST_TYPE ( 8 ) )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get hub descriptor
|
* Get hub descriptor
|
||||||
*
|
*
|
||||||
|
@ -214,6 +219,34 @@ usb_hub_set_hub_depth ( struct usb_device *usb, unsigned int depth ) {
|
||||||
return usb_control ( usb, USB_HUB_SET_HUB_DEPTH, depth, 0, NULL, 0 );
|
return usb_control ( usb, USB_HUB_SET_HUB_DEPTH, depth, 0, NULL, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear transaction translator buffer
|
||||||
|
*
|
||||||
|
* @v usb USB device
|
||||||
|
* @v device Device address
|
||||||
|
* @v endpoint Endpoint address
|
||||||
|
* @v attributes Endpoint attributes
|
||||||
|
* @v tt_port Transaction translator port (or 1 for single-TT hubs)
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
usb_hub_clear_tt_buffer ( struct usb_device *usb, unsigned int device,
|
||||||
|
unsigned int endpoint, unsigned int attributes,
|
||||||
|
unsigned int tt_port ) {
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
/* Calculate value */
|
||||||
|
value = ( ( ( endpoint & USB_ENDPOINT_MAX ) << 0 ) | ( device << 4 ) |
|
||||||
|
( ( attributes & USB_ENDPOINT_ATTR_TYPE_MASK ) << 11 ) |
|
||||||
|
( ( endpoint & USB_ENDPOINT_IN ) << 8 ) );
|
||||||
|
|
||||||
|
return usb_control ( usb, USB_HUB_CLEAR_TT_BUFFER, value,
|
||||||
|
tt_port, NULL, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transaction translator port value for single-TT hubs */
|
||||||
|
#define USB_HUB_TT_SINGLE 1
|
||||||
|
|
||||||
/** A USB hub device */
|
/** A USB hub device */
|
||||||
struct usb_hub_device {
|
struct usb_hub_device {
|
||||||
/** Name */
|
/** Name */
|
||||||
|
|
|
@ -2992,6 +2992,25 @@ static int xhci_hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear transaction translator buffer
|
||||||
|
*
|
||||||
|
* @v hub USB hub
|
||||||
|
* @v port USB port
|
||||||
|
* @v ep USB endpoint
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int xhci_hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
|
||||||
|
struct usb_endpoint *ep ) {
|
||||||
|
struct ehci_device *ehci = usb_hub_get_drvdata ( hub );
|
||||||
|
|
||||||
|
/* Should never be called; this is a root hub */
|
||||||
|
DBGC ( ehci, "XHCI %p port %d nonsensical CLEAR_TT for %s endpoint "
|
||||||
|
"%02x\n", ehci, port->address, ep->usb->name, ep->address );
|
||||||
|
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* PCI interface
|
* PCI interface
|
||||||
|
@ -3025,6 +3044,7 @@ static struct usb_host_operations xhci_operations = {
|
||||||
.enable = xhci_hub_enable,
|
.enable = xhci_hub_enable,
|
||||||
.disable = xhci_hub_disable,
|
.disable = xhci_hub_disable,
|
||||||
.speed = xhci_hub_speed,
|
.speed = xhci_hub_speed,
|
||||||
|
.clear_tt = xhci_hub_clear_tt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -820,6 +820,15 @@ struct usb_hub_driver_operations {
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int ( * speed ) ( struct usb_hub *hub, struct usb_port *port );
|
int ( * speed ) ( struct usb_hub *hub, struct usb_port *port );
|
||||||
|
/** Clear transaction translator buffer
|
||||||
|
*
|
||||||
|
* @v hub USB hub
|
||||||
|
* @v port USB port
|
||||||
|
* @v ep USB endpoint
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
int ( * clear_tt ) ( struct usb_hub *hub, struct usb_port *port,
|
||||||
|
struct usb_endpoint *ep );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue