The real VIA south bridges implement a PCI IRQ router which is configured by the BIOS or the OS. In order to respect these configurations, QEMU needs to implement it as well.
Note: The implementation was taken from piix4_set_irq() in hw/isa/piix4. Signed-off-by: Bernhard Beschow <shen...@gmail.com> --- hw/isa/vt82c686.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 3f9bd0c04d..f24e387d63 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -604,6 +604,48 @@ static void via_isa_request_i8259_irq(void *opaque, int irq, int level) qemu_set_irq(s->cpu_intr, level); } +static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num) +{ + switch (irq_num) { + case 0: + return s->dev.config[0x55] >> 4; + + case 1: + return s->dev.config[0x56] & 0xf; + + case 2: + return s->dev.config[0x56] >> 4; + + case 3: + return s->dev.config[0x57] >> 4; + } + + return 0; +} + +static void via_isa_set_pci_irq(void *opaque, int irq_num, int level) +{ + ViaISAState *s = opaque; + PCIBus *bus = pci_get_bus(&s->dev); + int pic_irq; + + /* now we change the pic irq level according to the via irq mappings */ + /* XXX: optimize */ + pic_irq = via_isa_get_pci_irq(s, irq_num); + if (pic_irq < ISA_NUM_IRQS) { + int i, pic_level; + + /* The pic level is the logical OR of all the PCI irqs mapped to it. */ + pic_level = 0; + for (i = 0; i < PCI_NUM_PINS; i++) { + if (pic_irq == via_isa_get_pci_irq(s, i)) { + pic_level |= pci_bus_get_irq_level(bus, i); + } + } + qemu_set_irq(s->isa_irqs[pic_irq], pic_level); + } +} + static void via_isa_realize(PCIDevice *d, Error **errp) { ViaISAState *s = VIA_ISA(d); @@ -676,6 +718,8 @@ static void via_isa_realize(PCIDevice *d, Error **errp) if (!qdev_realize(DEVICE(&s->mc97), BUS(pci_bus), errp)) { return; } + + pci_bus_irqs(pci_bus, via_isa_set_pci_irq, s, PCI_NUM_PINS); } /* TYPE_VT82C686B_ISA */ -- 2.39.2