diff options
-rw-r--r-- | src/drivers/usb/ehci.c | 26 | ||||
-rw-r--r-- | src/drivers/usb/ehci.h | 2 | ||||
-rw-r--r-- | src/include/ipxe/pci.h | 1 |
3 files changed, 29 insertions, 0 deletions
diff --git a/src/drivers/usb/ehci.c b/src/drivers/usb/ehci.c index e847c6b7..516ffd8c 100644 --- a/src/drivers/usb/ehci.c +++ b/src/drivers/usb/ehci.c @@ -337,6 +337,32 @@ static void ehci_poll_companions ( struct ehci_device *ehci ) { } } +/** + * Locate EHCI companion controller + * + * @v pci PCI device + * @ret busdevfn EHCI companion controller bus:dev.fn (if any) + */ +unsigned int ehci_companion ( struct pci_device *pci ) { + struct pci_device tmp; + unsigned int busdevfn; + int rc; + + /* Look for an EHCI function on the same PCI device */ + busdevfn = pci->busdevfn; + while ( ++busdevfn <= PCI_LAST_FUNC ( pci->busdevfn ) ) { + pci_init ( &tmp, busdevfn ); + if ( ( rc = pci_read_config ( &tmp ) ) != 0 ) + continue; + if ( tmp.class == PCI_CLASS ( PCI_CLASS_SERIAL, + PCI_CLASS_SERIAL_USB, + PCI_CLASS_SERIAL_USB_EHCI ) ) + return busdevfn; + } + + return 0; +} + /****************************************************************************** * * Run / stop / reset diff --git a/src/drivers/usb/ehci.h b/src/drivers/usb/ehci.h index d8814ec7..f35a07ce 100644 --- a/src/drivers/usb/ehci.h +++ b/src/drivers/usb/ehci.h @@ -537,4 +537,6 @@ struct ehci_endpoint { struct ehci_ring ring; }; +extern unsigned int ehci_companion ( struct pci_device *pci ); + #endif /* _IPXE_EHCI_H */ diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h index ccc42fee..a841e00f 100644 --- a/src/include/ipxe/pci.h +++ b/src/include/ipxe/pci.h @@ -239,6 +239,7 @@ struct pci_driver { #define PCI_BUSDEVFN( bus, slot, func ) \ ( ( (bus) << 8 ) | ( (slot) << 3 ) | ( (func) << 0 ) ) #define PCI_FIRST_FUNC( busdevfn ) ( (busdevfn) & ~0x07 ) +#define PCI_LAST_FUNC( busdevfn ) ( (busdevfn) | 0x07 ) #define PCI_BASE_CLASS( class ) ( (class) >> 16 ) #define PCI_SUB_CLASS( class ) ( ( (class) >> 8 ) & 0xff ) |