@@ -16,6 +16,7 @@
#include "qemu/osdep.h"
#include "hw/isa/vt82c686.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
#include "hw/qdev-properties.h"
#include "hw/ide/pci.h"
#include "hw/isa/isa.h"
@@ -604,6 +605,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_pic_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_pic_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_pic_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_pic_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 +719,9 @@ 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_pic_irq, pci_bus->map_irq,
+ s, ISA_NUM_IRQS);
}
/* TYPE_VT82C686B_ISA */
Both VIA south bridges allow system software to configure the routing of PCI interrupts to ISA interrupts. Implement this to model the real hardware more closely. The implementation is based on hw/isa/piix4.c. Signed-off-by: Bernhard Beschow <shentey@gmail.com> --- hw/isa/vt82c686.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)