mirror of https://github.com/ipxe/ipxe.git
[usb] Clear transaction translator buffers when applicable
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/35/head
parent
9e88194655
commit
5486c947e2
|
@ -321,6 +321,37 @@ int usb_endpoint_open ( struct usb_endpoint *ep ) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear transaction translator (if applicable)
|
||||||
|
*
|
||||||
|
* @v ep USB endpoint
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
|
static int usb_endpoint_clear_tt ( struct usb_endpoint *ep ) {
|
||||||
|
struct usb_device *usb = ep->usb;
|
||||||
|
struct usb_port *tt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Do nothing if this is a periodic endpoint */
|
||||||
|
if ( ep->attributes & USB_ENDPOINT_ATTR_PERIODIC )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Do nothing if this endpoint is not behind a transaction translator */
|
||||||
|
tt = usb_transaction_translator ( usb );
|
||||||
|
if ( ! tt )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Clear transaction translator buffer */
|
||||||
|
if ( ( rc = tt->hub->driver->clear_tt ( tt->hub, tt, ep ) ) != 0 ) {
|
||||||
|
DBGC ( usb, "USB %s %s could not clear transaction translator: "
|
||||||
|
"%s\n", usb->name, usb_endpoint_name ( ep->address ),
|
||||||
|
strerror ( rc ) );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close USB endpoint
|
* Close USB endpoint
|
||||||
*
|
*
|
||||||
|
@ -345,6 +376,9 @@ void usb_endpoint_close ( struct usb_endpoint *ep ) {
|
||||||
/* Discard any recycled buffers, if applicable */
|
/* Discard any recycled buffers, if applicable */
|
||||||
if ( ep->max )
|
if ( ep->max )
|
||||||
usb_flush ( ep );
|
usb_flush ( ep );
|
||||||
|
|
||||||
|
/* Clear transaction translator, if applicable */
|
||||||
|
usb_endpoint_clear_tt ( ep );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -369,6 +403,10 @@ static int usb_endpoint_reset ( struct usb_endpoint *ep ) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear transaction translator, if applicable */
|
||||||
|
if ( ( rc = usb_endpoint_clear_tt ( ep ) ) != 0 )
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* Clear endpoint halt, if applicable */
|
/* Clear endpoint halt, if applicable */
|
||||||
type = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
|
type = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK );
|
||||||
if ( ( type != USB_ENDPOINT_ATTR_CONTROL ) &&
|
if ( ( type != USB_ENDPOINT_ATTR_CONTROL ) &&
|
||||||
|
@ -1949,14 +1987,16 @@ void usb_free_address ( struct usb_bus *bus, unsigned int address ) {
|
||||||
* @ret route USB route string
|
* @ret route USB route string
|
||||||
*/
|
*/
|
||||||
unsigned int usb_route_string ( struct usb_device *usb ) {
|
unsigned int usb_route_string ( struct usb_device *usb ) {
|
||||||
|
struct usb_device *parent;
|
||||||
unsigned int route;
|
unsigned int route;
|
||||||
|
|
||||||
/* Navigate up to root hub, constructing route string as we go */
|
/* Navigate up to root hub, constructing route string as we go */
|
||||||
for ( route = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb ) {
|
for ( route = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
|
||||||
route <<= 4;
|
route <<= 4;
|
||||||
route |= ( ( usb->port->address > 0xf ) ?
|
route |= ( ( usb->port->address > 0xf ) ?
|
||||||
0xf : usb->port->address );
|
0xf : usb->port->address );
|
||||||
}
|
}
|
||||||
|
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1967,10 +2007,11 @@ unsigned int usb_route_string ( struct usb_device *usb ) {
|
||||||
* @ret depth Hub depth
|
* @ret depth Hub depth
|
||||||
*/
|
*/
|
||||||
unsigned int usb_depth ( struct usb_device *usb ) {
|
unsigned int usb_depth ( struct usb_device *usb ) {
|
||||||
|
struct usb_device *parent;
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
|
|
||||||
/* Navigate up to root hub, constructing depth as we go */
|
/* Navigate up to root hub, constructing depth as we go */
|
||||||
for ( depth = 0 ; usb->port->hub->usb ; usb = usb->port->hub->usb )
|
for ( depth = 0 ; ( parent = usb->port->hub->usb ) ; usb = parent )
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
|
@ -1983,14 +2024,37 @@ unsigned int usb_depth ( struct usb_device *usb ) {
|
||||||
* @ret port Root hub port
|
* @ret port Root hub port
|
||||||
*/
|
*/
|
||||||
struct usb_port * usb_root_hub_port ( struct usb_device *usb ) {
|
struct usb_port * usb_root_hub_port ( struct usb_device *usb ) {
|
||||||
|
struct usb_device *parent;
|
||||||
|
|
||||||
/* Navigate up to root hub */
|
/* Navigate up to root hub */
|
||||||
while ( usb->port->hub->usb )
|
while ( ( parent = usb->port->hub->usb ) )
|
||||||
usb = usb->port->hub->usb;
|
usb = parent;
|
||||||
|
|
||||||
return usb->port;
|
return usb->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get USB transaction translator
|
||||||
|
*
|
||||||
|
* @v usb USB device
|
||||||
|
* @ret port Transaction translator port, or NULL
|
||||||
|
*/
|
||||||
|
struct usb_port * usb_transaction_translator ( struct usb_device *usb ) {
|
||||||
|
struct usb_device *parent;
|
||||||
|
|
||||||
|
/* Navigate up to root hub. If we find a low-speed or
|
||||||
|
* full-speed port with a higher-speed parent device, then
|
||||||
|
* that port is the transaction translator.
|
||||||
|
*/
|
||||||
|
for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
|
||||||
|
if ( ( usb->port->speed <= USB_SPEED_FULL ) &&
|
||||||
|
( parent->port->speed > USB_SPEED_FULL ) )
|
||||||
|
return usb->port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Drag in objects via register_usb_bus() */
|
/* Drag in objects via register_usb_bus() */
|
||||||
REQUIRING_SYMBOL ( register_usb_bus );
|
REQUIRING_SYMBOL ( register_usb_bus );
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,9 @@ struct usb_endpoint_descriptor {
|
||||||
/** Endpoint attribute transfer type mask */
|
/** Endpoint attribute transfer type mask */
|
||||||
#define USB_ENDPOINT_ATTR_TYPE_MASK 0x03
|
#define USB_ENDPOINT_ATTR_TYPE_MASK 0x03
|
||||||
|
|
||||||
|
/** Endpoint periodic type */
|
||||||
|
#define USB_ENDPOINT_ATTR_PERIODIC 0x01
|
||||||
|
|
||||||
/** Control endpoint transfer type */
|
/** Control endpoint transfer type */
|
||||||
#define USB_ENDPOINT_ATTR_CONTROL 0x00
|
#define USB_ENDPOINT_ATTR_CONTROL 0x00
|
||||||
|
|
||||||
|
@ -1189,6 +1192,7 @@ extern void usb_free_address ( struct usb_bus *bus, unsigned int address );
|
||||||
extern unsigned int usb_route_string ( struct usb_device *usb );
|
extern unsigned int usb_route_string ( struct usb_device *usb );
|
||||||
extern unsigned int usb_depth ( struct usb_device *usb );
|
extern unsigned int usb_depth ( struct usb_device *usb );
|
||||||
extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
|
extern struct usb_port * usb_root_hub_port ( struct usb_device *usb );
|
||||||
|
extern struct usb_port * usb_transaction_translator ( struct usb_device *usb );
|
||||||
|
|
||||||
/** Minimum reset time
|
/** Minimum reset time
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue