@@ -761,6 +761,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
return NULL;
}
pci_dev->bus = bus;
+ if (bus->dma_context_fn) {
+ pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
+ }
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
@@ -2004,6 +2007,12 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
k->bus_info = &pci_bus_info;
}
+void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
+{
+ bus->dma_context_fn = fn;
+ bus->dma_context_opaque = opaque;
+}
+
static TypeInfo pci_device_type_info = {
.name = TYPE_PCI_DEVICE,
.parent = TYPE_DEVICE,
@@ -175,6 +175,7 @@ typedef struct PCIDeviceClass {
struct PCIDevice {
DeviceState qdev;
+
/* PCI config space */
uint8_t *config;
@@ -196,6 +197,7 @@ struct PCIDevice {
uint32_t devfn;
char name[64];
PCIIORegion io_regions[PCI_NUM_REGIONS];
+ DMAContext *dma;
/* do not access the following fields */
PCIConfigReadFunc *config_read;
@@ -316,6 +318,10 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
void pci_device_deassert_intx(PCIDevice *dev);
+typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
+
+void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
+
static inline void
pci_set_byte(uint8_t *config, uint8_t val)
{
@@ -552,8 +558,7 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
/* DMA access functions */
static inline DMAContext *pci_dma_context(PCIDevice *dev)
{
- /* Stub for when we have no PCI iommu support */
- return NULL;
+ return dev->dma;
}
static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
@@ -16,6 +16,8 @@ extern struct BusInfo pci_bus_info;
struct PCIBus {
BusState qbus;
+ PCIDMAContextFunc dma_context_fn;
+ void *dma_context_opaque;
uint8_t devfn_min;
pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq;