mirror of https://github.com/xemu-project/xemu.git
malta: Move PCI interrupt handling from gt64xxx_pci to piix4
Handling PCI interrupts in piix4 increases cohesion and reduces differences between piix4 and piix3. Signed-off-by: Bernhard Beschow <shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20220217101924.15347-3-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
parent
c291635867
commit
a7fc988051
|
@ -45,6 +45,7 @@ struct PIIX4State {
|
||||||
PCIDevice dev;
|
PCIDevice dev;
|
||||||
qemu_irq cpu_intr;
|
qemu_irq cpu_intr;
|
||||||
qemu_irq *isa;
|
qemu_irq *isa;
|
||||||
|
qemu_irq i8259[ISA_NUM_IRQS];
|
||||||
|
|
||||||
RTCState rtc;
|
RTCState rtc;
|
||||||
/* Reset Control Register */
|
/* Reset Control Register */
|
||||||
|
@ -54,6 +55,27 @@ struct PIIX4State {
|
||||||
|
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE)
|
OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE)
|
||||||
|
|
||||||
|
static void piix4_set_irq(void *opaque, int irq_num, int level)
|
||||||
|
{
|
||||||
|
int i, pic_irq, pic_level;
|
||||||
|
qemu_irq *pic = opaque;
|
||||||
|
PCIBus *bus = pci_get_bus(piix4_dev);
|
||||||
|
|
||||||
|
/* now we change the pic irq level according to the piix irq mappings */
|
||||||
|
/* XXX: optimize */
|
||||||
|
pic_irq = piix4_dev->config[PIIX_PIRQCA + irq_num];
|
||||||
|
if (pic_irq < 16) {
|
||||||
|
/* The pic level is the logical OR of all the PCI irqs mapped to it. */
|
||||||
|
pic_level = 0;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (pic_irq == piix4_dev->config[PIIX_PIRQCA + i]) {
|
||||||
|
pic_level |= pci_bus_get_irq_level(bus, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qemu_set_irq(pic[pic_irq], pic_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void piix4_isa_reset(DeviceState *dev)
|
static void piix4_isa_reset(DeviceState *dev)
|
||||||
{
|
{
|
||||||
PIIX4State *d = PIIX4_PCI_DEVICE(dev);
|
PIIX4State *d = PIIX4_PCI_DEVICE(dev);
|
||||||
|
@ -248,8 +270,34 @@ static void piix4_register_types(void)
|
||||||
|
|
||||||
type_init(piix4_register_types)
|
type_init(piix4_register_types)
|
||||||
|
|
||||||
|
static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
|
||||||
|
{
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
slot = PCI_SLOT(pci_dev->devfn);
|
||||||
|
|
||||||
|
switch (slot) {
|
||||||
|
/* PIIX4 USB */
|
||||||
|
case 10:
|
||||||
|
return 3;
|
||||||
|
/* AMD 79C973 Ethernet */
|
||||||
|
case 11:
|
||||||
|
return 1;
|
||||||
|
/* Crystal 4281 Sound */
|
||||||
|
case 12:
|
||||||
|
return 2;
|
||||||
|
/* PCI slot 1 to 4 */
|
||||||
|
case 18 ... 21:
|
||||||
|
return ((slot - 18) + irq_num) & 0x03;
|
||||||
|
/* Unknown device, don't do any translation */
|
||||||
|
default:
|
||||||
|
return irq_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
|
DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
|
||||||
{
|
{
|
||||||
|
PIIX4State *s;
|
||||||
PCIDevice *pci;
|
PCIDevice *pci;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
int devfn = PCI_DEVFN(10, 0);
|
int devfn = PCI_DEVFN(10, 0);
|
||||||
|
@ -257,6 +305,7 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
|
||||||
pci = pci_create_simple_multifunction(pci_bus, devfn, true,
|
pci = pci_create_simple_multifunction(pci_bus, devfn, true,
|
||||||
TYPE_PIIX4_PCI_DEVICE);
|
TYPE_PIIX4_PCI_DEVICE);
|
||||||
dev = DEVICE(pci);
|
dev = DEVICE(pci);
|
||||||
|
s = PIIX4_PCI_DEVICE(pci);
|
||||||
if (isa_bus) {
|
if (isa_bus) {
|
||||||
*isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
|
*isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
|
||||||
}
|
}
|
||||||
|
@ -271,5 +320,11 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s->i8259, 4);
|
||||||
|
|
||||||
|
for (int i = 0; i < ISA_NUM_IRQS; i++) {
|
||||||
|
s->i8259[i] = qdev_get_gpio_in_named(dev, "isa", i);
|
||||||
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "hw/mips/mips.h"
|
#include "hw/mips/mips.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "hw/pci/pci_host.h"
|
#include "hw/pci/pci_host.h"
|
||||||
#include "hw/southbridge/piix.h"
|
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "hw/intc/i8259.h"
|
#include "hw/intc/i8259.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
|
@ -981,53 +980,6 @@ static const MemoryRegionOps isd_mem_ops = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
|
|
||||||
{
|
|
||||||
int slot;
|
|
||||||
|
|
||||||
slot = PCI_SLOT(pci_dev->devfn);
|
|
||||||
|
|
||||||
switch (slot) {
|
|
||||||
/* PIIX4 USB */
|
|
||||||
case 10:
|
|
||||||
return 3;
|
|
||||||
/* AMD 79C973 Ethernet */
|
|
||||||
case 11:
|
|
||||||
return 1;
|
|
||||||
/* Crystal 4281 Sound */
|
|
||||||
case 12:
|
|
||||||
return 2;
|
|
||||||
/* PCI slot 1 to 4 */
|
|
||||||
case 18 ... 21:
|
|
||||||
return ((slot - 18) + irq_num) & 0x03;
|
|
||||||
/* Unknown device, don't do any translation */
|
|
||||||
default:
|
|
||||||
return irq_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
|
|
||||||
{
|
|
||||||
int i, pic_irq, pic_level;
|
|
||||||
qemu_irq *pic = opaque;
|
|
||||||
PCIBus *bus = pci_get_bus(piix4_dev);
|
|
||||||
|
|
||||||
/* now we change the pic irq level according to the piix irq mappings */
|
|
||||||
/* XXX: optimize */
|
|
||||||
pic_irq = piix4_dev->config[PIIX_PIRQCA + irq_num];
|
|
||||||
if (pic_irq < 16) {
|
|
||||||
/* The pic level is the logical OR of all the PCI irqs mapped to it. */
|
|
||||||
pic_level = 0;
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
if (pic_irq == piix4_dev->config[PIIX_PIRQCA + i]) {
|
|
||||||
pic_level |= pci_bus_get_irq_level(bus, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qemu_set_irq(pic[pic_irq], pic_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void gt64120_reset(DeviceState *dev)
|
static void gt64120_reset(DeviceState *dev)
|
||||||
{
|
{
|
||||||
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
|
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
|
||||||
|
@ -1204,7 +1156,7 @@ static void gt64120_realize(DeviceState *dev, Error **errp)
|
||||||
"gt64120-isd", 0x1000);
|
"gt64120-isd", 0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
PCIBus *gt64120_register(qemu_irq *pic)
|
PCIBus *gt64120_register(void)
|
||||||
{
|
{
|
||||||
GT64120State *d;
|
GT64120State *d;
|
||||||
PCIHostState *phb;
|
PCIHostState *phb;
|
||||||
|
@ -1215,12 +1167,10 @@ PCIBus *gt64120_register(qemu_irq *pic)
|
||||||
phb = PCI_HOST_BRIDGE(dev);
|
phb = PCI_HOST_BRIDGE(dev);
|
||||||
memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", 4 * GiB);
|
memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", 4 * GiB);
|
||||||
address_space_init(&d->pci0_mem_as, &d->pci0_mem, "pci0-mem");
|
address_space_init(&d->pci0_mem_as, &d->pci0_mem, "pci0-mem");
|
||||||
phb->bus = pci_register_root_bus(dev, "pci",
|
phb->bus = pci_root_bus_new(dev, "pci",
|
||||||
gt64120_pci_set_irq, gt64120_pci_map_irq,
|
&d->pci0_mem,
|
||||||
pic,
|
get_system_io(),
|
||||||
&d->pci0_mem,
|
PCI_DEVFN(18, 0), TYPE_PCI_BUS);
|
||||||
get_system_io(),
|
|
||||||
PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
|
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||||
|
|
||||||
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
|
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
|
||||||
|
|
|
@ -97,7 +97,6 @@ struct MaltaState {
|
||||||
|
|
||||||
Clock *cpuclk;
|
Clock *cpuclk;
|
||||||
MIPSCPSState cps;
|
MIPSCPSState cps;
|
||||||
qemu_irq i8259[ISA_NUM_IRQS];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct _loaderparams {
|
static struct _loaderparams {
|
||||||
|
@ -1391,7 +1390,7 @@ void mips_malta_init(MachineState *machine)
|
||||||
stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
|
stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
|
||||||
|
|
||||||
/* Northbridge */
|
/* Northbridge */
|
||||||
pci_bus = gt64120_register(s->i8259);
|
pci_bus = gt64120_register();
|
||||||
/*
|
/*
|
||||||
* The whole address space decoded by the GT-64120A doesn't generate
|
* The whole address space decoded by the GT-64120A doesn't generate
|
||||||
* exception when accessing invalid memory. Create an empty slot to
|
* exception when accessing invalid memory. Create an empty slot to
|
||||||
|
@ -1404,9 +1403,6 @@ void mips_malta_init(MachineState *machine)
|
||||||
|
|
||||||
/* Interrupt controller */
|
/* Interrupt controller */
|
||||||
qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq);
|
qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq);
|
||||||
for (int i = 0; i < ISA_NUM_IRQS; i++) {
|
|
||||||
s->i8259[i] = qdev_get_gpio_in_named(dev, "isa", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate SPD EEPROM data */
|
/* generate SPD EEPROM data */
|
||||||
generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
|
generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
|
|
||||||
/* gt64xxx.c */
|
/* gt64xxx.c */
|
||||||
PCIBus *gt64120_register(qemu_irq *pic);
|
PCIBus *gt64120_register(void);
|
||||||
|
|
||||||
/* bonito.c */
|
/* bonito.c */
|
||||||
PCIBus *bonito_init(qemu_irq *pic);
|
PCIBus *bonito_init(qemu_irq *pic);
|
||||||
|
|
Loading…
Reference in New Issue