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


Reply via email to