summaryrefslogtreecommitdiffstats
path: root/src/drivers/bus
diff options
context:
space:
mode:
authorMichael Brown2015-03-23 21:24:20 +0100
committerMichael Brown2015-03-23 21:24:20 +0100
commitf557794ab3ccae444653a25b889cc51d10e6f0c3 (patch)
tree2034d103fa624aec631180d201c3c4aa4a50607d /src/drivers/bus
parent[usb] Improve debug messages for failed control transactions (diff)
downloadipxe-f557794ab3ccae444653a25b889cc51d10e6f0c3.tar.gz
ipxe-f557794ab3ccae444653a25b889cc51d10e6f0c3.tar.xz
ipxe-f557794ab3ccae444653a25b889cc51d10e6f0c3.zip
[xhci] Support USB1 devices attached via transaction translators
xHCI provides a somewhat convoluted mechanism for specifying details of a transaction translator. Hubs must be marked as such in the device slot context. The only opportunity to do so is as part of a Configure Endpoint command, which can be executed only when opening the hub's interrupt endpoint. We add a mechanism for host controllers to intercept the opening of hub devices, providing xHCI with an opportunity to update the internal device slot structure for the corresponding USB device to indicate that the device is a hub. We then include the hub-specific details in the input context whenever any Configure Endpoint command is issued. When a device is opened, we record the device slot and port for its transaction translator (if any), and supply these as part of the Address Device command. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/bus')
-rw-r--r--src/drivers/bus/usb.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c
index 1b610379..f53f7461 100644
--- a/src/drivers/bus/usb.c
+++ b/src/drivers/bus/usb.c
@@ -1692,6 +1692,7 @@ struct usb_hub * alloc_usb_hub ( struct usb_bus *bus, struct usb_device *usb,
hub->protocol = usb->port->protocol;
hub->ports = ports;
hub->driver = driver;
+ hub->host = &bus->op->hub;
/* Initialise port list */
for ( i = 1 ; i <= hub->ports ; i++ ) {
@@ -1721,11 +1722,18 @@ int register_usb_hub ( struct usb_hub *hub ) {
/* Add to hub list */
list_add_tail ( &hub->list, &bus->hubs );
- /* Open hub */
+ /* Open hub (host controller) */
+ if ( ( rc = hub->host->open ( hub ) ) != 0 ) {
+ DBGC ( hub, "USB hub %s could not open: %s\n",
+ hub->name, strerror ( rc ) );
+ goto err_host_open;
+ }
+
+ /* Open hub (driver) */
if ( ( rc = hub->driver->open ( hub ) ) != 0 ) {
DBGC ( hub, "USB hub %s could not open: %s\n",
hub->name, strerror ( rc ) );
- goto err_open;
+ goto err_driver_open;
}
/* Delay to allow ports to stabilise */
@@ -1747,7 +1755,9 @@ int register_usb_hub ( struct usb_hub *hub ) {
return 0;
hub->driver->close ( hub );
- err_open:
+ err_driver_open:
+ hub->host->close ( hub );
+ err_host_open:
list_del ( &hub->list );
return rc;
}
@@ -1768,9 +1778,12 @@ void unregister_usb_hub ( struct usb_hub *hub ) {
usb_detached ( port );
}
- /* Close hub */
+ /* Close hub (driver) */
hub->driver->close ( hub );
+ /* Close hub (host controller) */
+ hub->host->close ( hub );
+
/* Cancel any pending port status changes */
for ( i = 1 ; i <= hub->ports ; i++ ) {
port = usb_port ( hub, i );
@@ -1839,7 +1852,7 @@ struct usb_bus * alloc_usb_bus ( struct device *dev, unsigned int ports,
bus->host = &bus->op->bus;
/* Allocate root hub */
- bus->hub = alloc_usb_hub ( bus, NULL, ports, &op->hub );
+ bus->hub = alloc_usb_hub ( bus, NULL, ports, &op->root );
if ( ! bus->hub )
goto err_alloc_hub;