Simple search code used to find first instance of a PCIe Designated Vendor-Specific Extended Capability.
Signed-off-by: Jonathan Cameron <jonathan.came...@huawei.com> --- include/hw/pci/pcie.h | 1 + hw/pci/pcie.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 11f5a91bbb..ff559a6653 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -127,6 +127,7 @@ bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev); /* PCI express extended capability helper functions */ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id); +uint16_t pcie_find_dvsec(PCIDevice *dev, uint16_t vid, uint16_t id); void pcie_add_capability(PCIDevice *dev, uint16_t cap_id, uint8_t cap_ver, uint16_t offset, uint16_t size); diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6db0cf69cd..9f1ca718b5 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -944,6 +944,30 @@ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id) return pcie_find_capability_list(dev, cap_id, NULL); } +uint16_t pcie_find_dvsec(PCIDevice *dev, uint16_t vid, uint16_t id) +{ + uint16_t prev = 0; + uint16_t next; + + while (1) { + uint32_t head1; + + next = pcie_find_capability_list(dev, 0x23, &prev); + if (!next) { + break; + } + head1 = pci_get_long(dev->config + next + 4); + if ((head1 & 0xFFFF) == vid) { + uint16_t head2 = pci_get_word(dev->config + next + 8); + if (head2 == id) { + return next; + } + } + prev = next; + } + return 0; +} + static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next) { uint32_t header = pci_get_long(dev->config + pos); -- 2.39.2