diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/bus/pciextra.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c index 82287fb86..3082d8a3d 100644 --- a/src/drivers/bus/pciextra.c +++ b/src/drivers/bus/pciextra.c @@ -3,6 +3,24 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> #include <ipxe/pci.h> +static int pci_find_capability_common ( struct pci_device *pci, + uint8_t pos, int cap ) { + uint8_t id; + int ttl = 48; + + while ( ttl-- && pos >= 0x40 ) { + pos &= ~3; + pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); + DBG ( "PCI Capability: %d\n", id ); + if ( id == 0xff ) + break; + if ( id == cap ) + return pos; + pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); + } + return 0; +} + /** * Look for a PCI capability * @@ -17,9 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ int pci_find_capability ( struct pci_device *pci, int cap ) { uint16_t status; - uint8_t pos, id; + uint8_t pos; uint8_t hdr_type; - int ttl = 48; pci_read_config_word ( pci, PCI_STATUS, &status ); if ( ! ( status & PCI_STATUS_CAP_LIST ) ) @@ -36,17 +53,28 @@ int pci_find_capability ( struct pci_device *pci, int cap ) { pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos ); break; } - while ( ttl-- && pos >= 0x40 ) { - pos &= ~3; - pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); - DBG ( "PCI Capability: %d\n", id ); - if ( id == 0xff ) - break; - if ( id == cap ) - return pos; - pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); - } - return 0; + return pci_find_capability_common ( pci, pos, cap ); +} + +/** + * Look for another PCI capability + * + * @v pci PCI device to query + * @v pos Address of the current capability + * @v cap Capability code + * @ret address Address of capability, or 0 if not found + * + * Determine whether or not a device supports a given PCI capability + * starting the search at a given address within the device's PCI + * configuration space. Returns the address of the next capability + * structure within the device's PCI configuration space, or 0 if the + * device does not support another such capability. + */ +int pci_find_next_capability ( struct pci_device *pci, int pos, int cap ) { + uint8_t new_pos; + + pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos ); + return pci_find_capability_common ( pci, new_pos, cap ); } /** |
