[ipxe-devel] [PATCH 1/4] [pci] Add pci_find_next_capability
Michael S. Tsirkin
mst at redhat.com
Thu Mar 10 13:34:27 UTC 2016
On Wed, Mar 09, 2016 at 07:20:00PM +0100, Ladi Prosek wrote:
> PCI devices may support more capabilities of the same type (for
> example PCI_CAP_ID_VNDR) and there was no way to discover all of
> them. This commit adds a new API pci_find_next_capability which
> provides this functionality. It would typically be used like so:
>
> for (pos = pci_find_capability(pci, PCI_CAP_ID_VNDR);
> pos > 0;
> pos = pci_find_next_capability(pci, pos, PCI_CAP_ID_VNDR)) {
> ...
> }
>
> Signed-off-by: Ladi Prosek <lprosek at redhat.com>
Reviewed-by: Michael S. Tsirkin <mst at redhat.com>
> ---
> src/drivers/bus/pciextra.c | 54 +++++++++++++++++++++++++++++++++++-----------
> src/include/ipxe/pci.h | 2 ++
> 2 files changed, 43 insertions(+), 13 deletions(-)
>
> diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c
> index 82287fb..15f79c9 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 ) {
> + u8 new_pos;
> +
> + pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos );
> + return pci_find_capability_common ( pci, new_pos, cap );
> }
>
> /**
> diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h
> index 89d9d80..0c6bc7e 100644
> --- a/src/include/ipxe/pci.h
> +++ b/src/include/ipxe/pci.h
> @@ -286,6 +286,8 @@ extern int pci_find_driver ( struct pci_device *pci );
> extern int pci_probe ( struct pci_device *pci );
> extern void pci_remove ( struct pci_device *pci );
> extern int pci_find_capability ( struct pci_device *pci, int capability );
> +extern int pci_find_next_capability ( struct pci_device *pci,
> + int pos, int capability );
> extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg );
>
> /**
> --
> 2.5.0
More information about the ipxe-devel
mailing list