Allocate MAX_PCI_DEVICES IRQs for the pci_generic device. For now we assume that at every PCI slot corresponds an interrupt line: this also seems what the kernel code does when parsing the interrupt mapping from the device tree. At the moment there isn't a structure that keeps track of the IRQ mapping; it will be added later by a patch of this series.
Signed-off-by: Alvise Rigo <a.r...@virtualopensystems.com> --- hw/arm/virt.c | 10 ++++++---- hw/pci-host/generic-pci.c | 15 ++++++++++++--- include/hw/pci-host/pci_generic.h | 4 +++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index c93152f..a433902 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -41,6 +41,7 @@ #include "exec/address-spaces.h" #include "qemu/bitops.h" #include "qemu/error-report.h" +#include "hw/pci-host/pci_generic.h" /* Number of external interrupt lines to configure the GIC with */ @@ -359,6 +360,7 @@ static void create_pci_host(const VirtBoardInfo *vbi, qemu_irq *pic) SysBusDevice *busdev; uint32_t gic_phandle; char *nodename; + int i; hwaddr cfg_base = vbi->memmap[VIRT_PCI_CFG].base; hwaddr cfg_size = vbi->memmap[VIRT_PCI_CFG].size; hwaddr io_base = vbi->memmap[VIRT_PCI_IO].base; @@ -397,10 +399,10 @@ static void create_pci_host(const VirtBoardInfo *vbi, qemu_irq *pic) sysbus_mmio_map(busdev, 0, cfg_base); /* PCI config */ sysbus_mmio_map(busdev, 1, io_base); /* PCI I/O */ sysbus_mmio_map(busdev, 2, mem_base); /* PCI memory window */ - sysbus_connect_irq(busdev, 0, pic[4]); - sysbus_connect_irq(busdev, 1, pic[5]); - sysbus_connect_irq(busdev, 2, pic[6]); - sysbus_connect_irq(busdev, 3, pic[7]); + + for ( i = 0; i < MAX_PCI_DEVICES; i++) { + sysbus_connect_irq(busdev, i, pic[vbi->irqmap[VIRT_PCI_CFG] + i]); + } pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); pci_create_simple(pci_bus, -1, "pci-ohci"); diff --git a/hw/pci-host/generic-pci.c b/hw/pci-host/generic-pci.c index 8733c67..75aae45 100644 --- a/hw/pci-host/generic-pci.c +++ b/hw/pci-host/generic-pci.c @@ -65,18 +65,27 @@ static void pci_generic_host_init(Object *obj) qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); } +static int generic_pci_map_irq_fn(PCIDevice *pci_dev, int pin) +{ + if (!pin) { + return PCI_SLOT(pci_dev->devfn); + } + + hw_error("generic_pci: only one pin per device supported."); +} + static void pci_generic_host_realize(DeviceState *dev, Error **errp) { PCIVPBState *s = PCI_GEN(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); int i; - for (i = 0; i < 4; i++) { + for (i = 0; i < MAX_PCI_DEVICES; i++) { sysbus_init_irq(sbd, &s->irq[i]); } - pci_bus_irqs(&s->pci_bus, pci_generic_set_irq, pci_swizzle_map_irq_fn, - s->irq, 4); + pci_bus_irqs(&s->pci_bus, pci_generic_set_irq, generic_pci_map_irq_fn, + s->irq, MAX_PCI_DEVICES); /* Our memory regions are: * 0 : PCI config window diff --git a/include/hw/pci-host/pci_generic.h b/include/hw/pci-host/pci_generic.h index 46e4cb8..2367d80 100644 --- a/include/hw/pci-host/pci_generic.h +++ b/include/hw/pci-host/pci_generic.h @@ -5,10 +5,12 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" +#define MAX_PCI_DEVICES 10 + typedef struct { PCIHostState parent_obj; - qemu_irq irq[4]; + qemu_irq irq[MAX_PCI_DEVICES]; MemoryRegion mem_config; /* Containers representing the PCI address spaces */ MemoryRegion pci_io_space; -- 1.9.1