the pri configuration offset is also stored into the PCIExpressDevice
to make it easier to get the PRI status register
Signed-off-by: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com>
---
hw/pci/pcie.c | 25 +++++++++++++++++++++++++
include/hw/pci/pcie.h | 5 ++++-
include/hw/pci/pcie_regs.h | 4 ++++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 4efd84fed5..053bca6949 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -1202,6 +1202,31 @@ void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width,
dev->exp.pasid_cap = offset;
}
+/* PRI */
+void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap,
+ bool prg_response_pasid_req)
+{
+ static const uint16_t control_reg_rw_mask = 0x3;
+ static const uint16_t status_reg_rw1_mask = 0x3;
+ static const uint32_t pr_alloc_reg_rw_mask = 0xffffffff;
+
+ uint16_t status_reg = prg_response_pasid_req ? PCI_PRI_STATUS_PASID : 0;
+ status_reg |= PCI_PRI_STATUS_STOPPED; /* Stopped by default */
+
+ pcie_add_capability(dev, PCI_EXT_CAP_ID_PRI, PCI_PRI_VER, offset,
+ PCI_EXT_CAP_PRI_SIZEOF);
+ /* Disabled by default */
+
+ pci_set_word(dev->config + offset + PCI_PRI_STATUS, status_reg);
+ pci_set_long(dev->config + offset + PCI_PRI_MAX_REQ, outstanding_pr_cap);
+
+ pci_set_word(dev->wmask + offset + PCI_PRI_CTRL, control_reg_rw_mask);
+ pci_set_word(dev->w1cmask + offset + PCI_PRI_STATUS, status_reg_rw1_mask);
+ pci_set_long(dev->wmask + offset + PCI_PRI_ALLOC_REQ, pr_alloc_reg_rw_mask);
+
+ dev->exp.pri_cap = offset;
+}
+
bool pcie_pasid_enabled(const PCIDevice *dev)
{
if (!pci_is_express(dev) || !dev->exp.pasid_cap) {
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 0c127b29dc..198d6da817 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -72,9 +72,10 @@ struct PCIExpressDevice {
uint16_t aer_cap;
PCIEAERLog aer_log;
- /* Offset of ATS and PASID capabilities in config space */
+ /* Offset of ATS, PRI and PASID capabilities in config space */
uint16_t ats_cap;
uint16_t pasid_cap;
+ uint16_t pri_cap;
/* ACS */
uint16_t acs_cap;
@@ -154,6 +155,8 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width,
bool exec_perm, bool priv_mod);
+void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap,
+ bool prg_response_pasid_req);
bool pcie_pasid_enabled(const PCIDevice *dev);
bool pcie_ats_enabled(const PCIDevice *dev);
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 0a86598f80..bb8791d1b3 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -89,6 +89,10 @@ typedef enum PCIExpLinkWidth {
/* PASID */
#define PCI_PASID_VER 1
#define PCI_EXT_CAP_PASID_MAX_WIDTH 20
+
+/* PRI */
+#define PCI_PRI_VER 1
+
/* AER */
#define PCI_ERR_VER 2
#define PCI_ERR_SIZEOF 0x48
--
2.45.1