aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-08-09 19:44:55 +0300
committerAnthony Liguori <aliguori@us.ibm.com>2009-08-24 08:01:41 -0500
commit1452411b25fb207e7f442e5a5128f34b4939d31c (patch)
treec37ce00231c588133f2dfc9124c2b9b9f8ef6d5b
parent21d4e8e3efc66964d1cbe4dd0eb8f18303f84fa9 (diff)
downloadqemu-1452411b25fb207e7f442e5a5128f34b4939d31c.zip
qemu-1452411b25fb207e7f442e5a5128f34b4939d31c.tar.gz
qemu-1452411b25fb207e7f442e5a5128f34b4939d31c.tar.bz2
Route PC irqs to ISA bus instead of i8259 directly
A PC has its motherboard IRQ lines connected to both the PIC and IOAPIC. Currently, qemu routes IRQs to the PIC which then calls the IOAPIC, an incestuous arrangement. In order to clean this up, create a new ISA IRQ abstraction, and have devices raise ISA IRQs (which in turn raise the i8259 IRQs as usual). Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r--hw/pc.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/hw/pc.c b/hw/pc.c
index 09252ba..902d0ca 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -88,6 +88,17 @@ static void option_rom_setup_reset(target_phys_addr_t addr, unsigned size)
qemu_register_reset(option_rom_reset, rrd);
}
+typedef struct isa_irq_state {
+ qemu_irq *i8259;
+} IsaIrqState;
+
+static void isa_irq_handler(void *opaque, int n, int level)
+{
+ IsaIrqState *isa = (IsaIrqState *)opaque;
+
+ qemu_set_irq(isa->i8259[n], level);
+}
+
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
}
@@ -1122,7 +1133,9 @@ static void pc_init1(ram_addr_t ram_size,
int piix3_devfn = -1;
CPUState *env;
qemu_irq *cpu_irq;
+ qemu_irq *isa_irq;
qemu_irq *i8259;
+ IsaIrqState *isa_irq_state;
DriveInfo *dinfo;
BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
BlockDriverState *fd[MAX_FD];
@@ -1267,10 +1280,13 @@ static void pc_init1(ram_addr_t ram_size,
cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
i8259 = i8259_init(cpu_irq[0]);
- ferr_irq = i8259[13];
+ isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+ isa_irq_state->i8259 = i8259;
+ isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 16);
+ ferr_irq = isa_irq[13];
if (pci_enabled) {
- pci_bus = i440fx_init(&i440fx_state, i8259);
+ pci_bus = i440fx_init(&i440fx_state, isa_irq);
piix3_devfn = piix3_init(pci_bus, -1);
} else {
pci_bus = NULL;
@@ -1300,7 +1316,7 @@ static void pc_init1(ram_addr_t ram_size,
}
}
- rtc_state = rtc_init(0x70, i8259[8], 2000);
+ rtc_state = rtc_init(0x70, isa_irq[8], 2000);
qemu_register_boot_set(pc_boot_set, rtc_state);
@@ -1310,10 +1326,10 @@ static void pc_init1(ram_addr_t ram_size,
if (pci_enabled) {
ioapic = ioapic_init();
}
- pit = pit_init(0x40, i8259[0]);
+ pit = pit_init(0x40, isa_irq[0]);
pcspk_init(pit);
if (!no_hpet) {
- hpet_init(i8259);
+ hpet_init(isa_irq);
}
if (pci_enabled) {
pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
@@ -1321,14 +1337,14 @@ static void pc_init1(ram_addr_t ram_size,
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
- serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
+ serial_init(serial_io[i], isa_irq[serial_irq[i]], 115200,
serial_hds[i]);
}
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
if (parallel_hds[i]) {
- parallel_init(parallel_io[i], i8259[parallel_irq[i]],
+ parallel_init(parallel_io[i], isa_irq[parallel_irq[i]],
parallel_hds[i]);
}
}
@@ -1339,7 +1355,7 @@ static void pc_init1(ram_addr_t ram_size,
NICInfo *nd = &nd_table[i];
if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
- pc_init_ne2k_isa(nd, i8259);
+ pc_init_ne2k_isa(nd, isa_irq);
else
pci_nic_init(nd, "ne2k_pci", NULL);
}
@@ -1357,27 +1373,27 @@ static void pc_init1(ram_addr_t ram_size,
}
if (pci_enabled) {
- pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
+ pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, isa_irq);
} else {
for(i = 0; i < MAX_IDE_BUS; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], isa_irq[ide_irq[i]],
hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
}
}
isa_dev = isa_create_simple("i8042", 0x60, 0x64);
- isa_connect_irq(isa_dev, 0, i8259[1]);
- isa_connect_irq(isa_dev, 1, i8259[12]);
+ isa_connect_irq(isa_dev, 0, isa_irq[1]);
+ isa_connect_irq(isa_dev, 1, isa_irq[12]);
DMA_init(0);
#ifdef HAS_AUDIO
- audio_init(pci_enabled ? pci_bus : NULL, i8259);
+ audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
#endif
for(i = 0; i < MAX_FD; i++) {
dinfo = drive_get(IF_FLOPPY, 0, i);
fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+ floppy_controller = fdctrl_init(isa_irq[6], 2, 0, 0x3f0, fd);
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
@@ -1390,7 +1406,7 @@ static void pc_init1(ram_addr_t ram_size,
i2c_bus *smbus;
/* TODO: Populate SPD eeprom data. */
- smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);
+ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, isa_irq[9]);
for (i = 0; i < 8; i++) {
DeviceState *eeprom;
eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");