diff options
author | Michael Brown | 2015-03-23 21:24:20 +0100 |
---|---|---|
committer | Michael Brown | 2015-03-23 21:24:20 +0100 |
commit | f557794ab3ccae444653a25b889cc51d10e6f0c3 (patch) | |
tree | 2034d103fa624aec631180d201c3c4aa4a50607d /src/drivers/usb/ehci.c | |
parent | [usb] Improve debug messages for failed control transactions (diff) | |
download | ipxe-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/usb/ehci.c')
-rw-r--r-- | src/drivers/usb/ehci.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/src/drivers/usb/ehci.c b/src/drivers/usb/ehci.c index f912de35..4bff3fef 100644 --- a/src/drivers/usb/ehci.c +++ b/src/drivers/usb/ehci.c @@ -1332,6 +1332,35 @@ static int ehci_device_address ( struct usb_device *usb ) { /****************************************************************************** * + * Hub operations + * + ****************************************************************************** + */ + +/** + * Open hub + * + * @v hub USB hub + * @ret rc Return status code + */ +static int ehci_hub_open ( struct usb_hub *hub __unused ) { + + /* Nothing to do */ + return 0; +} + +/** + * Close hub + * + * @v hub USB hub + */ +static void ehci_hub_close ( struct usb_hub *hub __unused ) { + + /* Nothing to do */ +} + +/****************************************************************************** + * * Root hub operations * ****************************************************************************** @@ -1343,7 +1372,7 @@ static int ehci_device_address ( struct usb_device *usb ) { * @v hub USB hub * @ret rc Return status code */ -static int ehci_hub_open ( struct usb_hub *hub ) { +static int ehci_root_open ( struct usb_hub *hub ) { struct usb_bus *bus = hub->bus; struct ehci_device *ehci = usb_bus_get_hostdata ( bus ); uint32_t portsc; @@ -1374,7 +1403,7 @@ static int ehci_hub_open ( struct usb_hub *hub ) { * * @v hub USB hub */ -static void ehci_hub_close ( struct usb_hub *hub ) { +static void ehci_root_close ( struct usb_hub *hub ) { struct ehci_device *ehci = usb_hub_get_drvdata ( hub ); /* Route all ports back to companion controllers */ @@ -1391,7 +1420,7 @@ static void ehci_hub_close ( struct usb_hub *hub ) { * @v port USB port * @ret rc Return status code */ -static int ehci_hub_enable ( struct usb_hub *hub, struct usb_port *port ) { +static int ehci_root_enable ( struct usb_hub *hub, struct usb_port *port ) { struct ehci_device *ehci = usb_hub_get_drvdata ( hub ); uint32_t portsc; unsigned int line; @@ -1449,7 +1478,7 @@ static int ehci_hub_enable ( struct usb_hub *hub, struct usb_port *port ) { * @v port USB port * @ret rc Return status code */ -static int ehci_hub_disable ( struct usb_hub *hub, struct usb_port *port ) { +static int ehci_root_disable ( struct usb_hub *hub, struct usb_port *port ) { struct ehci_device *ehci = usb_hub_get_drvdata ( hub ); uint32_t portsc; @@ -1468,7 +1497,7 @@ static int ehci_hub_disable ( struct usb_hub *hub, struct usb_port *port ) { * @v port USB port * @ret rc Return status code */ -static int ehci_hub_speed ( struct usb_hub *hub, struct usb_port *port ) { +static int ehci_root_speed ( struct usb_hub *hub, struct usb_port *port ) { struct ehci_device *ehci = usb_hub_get_drvdata ( hub ); uint32_t portsc; unsigned int speed; @@ -1512,8 +1541,8 @@ static int ehci_hub_speed ( struct usb_hub *hub, struct usb_port *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 ) { +static int ehci_root_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 */ @@ -1529,7 +1558,7 @@ static int ehci_hub_clear_tt ( struct usb_hub *hub, struct usb_port *port, * @v hub USB hub * @v port USB port */ -static void ehci_hub_poll ( struct usb_hub *hub, struct usb_port *port ) { +static void ehci_root_poll ( struct usb_hub *hub, struct usb_port *port ) { struct ehci_device *ehci = usb_hub_get_drvdata ( hub ); uint32_t portsc; uint32_t change; @@ -1692,7 +1721,7 @@ static void ehci_bus_poll ( struct usb_bus *bus ) { /* Iterate over all ports looking for status changes */ for ( i = 1 ; i <= ehci->ports ; i++ ) - ehci_hub_poll ( hub, usb_port ( hub, i ) ); + ehci_root_poll ( hub, usb_port ( hub, i ) ); } /* Report fatal errors */ @@ -1730,10 +1759,14 @@ static struct usb_host_operations ehci_operations = { .hub = { .open = ehci_hub_open, .close = ehci_hub_close, - .enable = ehci_hub_enable, - .disable = ehci_hub_disable, - .speed = ehci_hub_speed, - .clear_tt = ehci_hub_clear_tt, + }, + .root = { + .open = ehci_root_open, + .close = ehci_root_close, + .enable = ehci_root_enable, + .disable = ehci_root_disable, + .speed = ehci_root_speed, + .clear_tt = ehci_root_clear_tt, }, }; |