summaryrefslogtreecommitdiff
path: root/include/hw/pci/pci.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/hw/pci/pci.h')
-rw-r--r--include/hw/pci/pci.h42
1 files changed, 38 insertions, 4 deletions
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index ef6ba51f6c..929ec2fb07 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -15,6 +15,7 @@
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
+#define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn))
#define PCI_SLOT_MAX 32
#define PCI_FUNC_MAX 8
@@ -173,6 +174,9 @@ enum {
/* PCI Express capability - Power Controller Present */
#define QEMU_PCIE_SLTCAP_PCP_BITNR 7
QEMU_PCIE_SLTCAP_PCP = (1 << QEMU_PCIE_SLTCAP_PCP_BITNR),
+ /* Link active status in endpoint capability is always set */
+#define QEMU_PCIE_LNKSTA_DLLLA_BITNR 8
+ QEMU_PCIE_LNKSTA_DLLLA = (1 << QEMU_PCIE_LNKSTA_DLLLA_BITNR),
};
#define TYPE_PCI_DEVICE "pci-device"
@@ -230,6 +234,20 @@ typedef void (*MSIVectorPollNotifier)(PCIDevice *dev,
unsigned int vector_start,
unsigned int vector_end);
+enum PCIReqIDType {
+ PCI_REQ_ID_INVALID = 0,
+ PCI_REQ_ID_BDF,
+ PCI_REQ_ID_SECONDARY_BUS,
+ PCI_REQ_ID_MAX,
+};
+typedef enum PCIReqIDType PCIReqIDType;
+
+struct PCIReqIDCache {
+ PCIDevice *dev;
+ PCIReqIDType type;
+};
+typedef struct PCIReqIDCache PCIReqIDCache;
+
struct PCIDevice {
DeviceState qdev;
@@ -252,6 +270,11 @@ struct PCIDevice {
/* the following fields are read only */
PCIBus *bus;
int32_t devfn;
+ /* Cached device to fetch requester ID from, to avoid the PCI
+ * tree walking every time we invoke PCI request (e.g.,
+ * MSI). For conventional PCI root complex, this field is
+ * meaningless. */
+ PCIReqIDCache requester_id_cache;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
AddressSpace bus_master_as;
@@ -465,16 +488,23 @@ pci_get_long(const uint8_t *config)
return ldl_le_p(config);
}
+/*
+ * PCI capabilities and/or their fields
+ * are generally DWORD aligned only so
+ * mechanism used by pci_set/get_quad()
+ * must be tolerant to unaligned pointers
+ *
+ */
static inline void
pci_set_quad(uint8_t *config, uint64_t val)
{
- cpu_to_le64w((uint64_t *)config, val);
+ stq_le_p(config, val);
}
static inline uint64_t
pci_get_quad(const uint8_t *config)
{
- return le64_to_cpup((const uint64_t *)config);
+ return ldq_le_p(config);
}
static inline void
@@ -685,11 +715,13 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
}
-static inline uint16_t pci_requester_id(PCIDevice *dev)
+static inline uint16_t pci_get_bdf(PCIDevice *dev)
{
- return (pci_bus_num(dev->bus) << 8) | dev->devfn;
+ return PCI_BUILD_BDF(pci_bus_num(dev->bus), dev->devfn);
}
+uint16_t pci_requester_id(PCIDevice *dev);
+
/* DMA access functions */
static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
{
@@ -776,4 +808,6 @@ extern const VMStateDescription vmstate_pci_device;
.offset = vmstate_offset_pointer(_state, _field, PCIDevice), \
}
+MSIMessage pci_get_msi_message(PCIDevice *dev, int vector);
+
#endif