Signed-off-by: Jim MacArthur <[email protected]>
---
hw/pci/pcie.c | 16 ++++++++++++++++
include/hw/pci/pcie.h | 4 ++++
2 files changed, 20 insertions(+)
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 42bcb9206d..42c4997b42 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -1157,6 +1157,22 @@ void pcie_add_capability(PCIDevice *dev,
memset(dev->cmask + offset, 0xFF, size);
}
+/*
+ * Add a DVSEC capability. As per pcie_add_capability, the caller must
+ * ensure (offset, size) does not overlap any other capability or extend
+ * past the extended configuration space.
+ */
+void pcie_add_dvsec_capability(PCIDevice *device, uint16_t capability_id,
+ uint8_t version, uint32_t offset,
+ uint16_t size_bytes, uint16_t vendor_id,
+ uint8_t dvsec_version, uint16_t dvsec_id)
+{
+ const uint32_t header1 = size_bytes << 20 | version << 16 | vendor_id;
+ pcie_add_capability(device, capability_id, version, offset, size_bytes);
+ pci_set_long(device->config + offset + 0x4, header1);
+ pci_set_word(device->config + offset + 0x8, dvsec_id);
+}
+
/*
* Sync the PCIe Link Status negotiated speed and width of a bridge with the
* downstream device. If downstream device is not present, re-write with the
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index ec25e7a7de..86c29f7d8b 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -133,6 +133,10 @@ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t
cap_id);
void pcie_add_capability(PCIDevice *dev,
uint16_t cap_id, uint8_t cap_ver,
uint16_t offset, uint16_t size);
+void pcie_add_dvsec_capability(PCIDevice *device, uint16_t capability_id,
+ uint8_t version, uint32_t offset,
+ uint16_t size_bytes, uint16_t vendor_id,
+ uint8_t dvsec_version, uint16_t dvsec_id);
bool pcie_insert_capability(PCIDevice *dev, uint16_t cap_id, uint8_t cap_ver,
uint16_t offset, uint16_t size);
void pcie_sync_bridge_lnk(PCIDevice *dev);
--
2.43.0