ebus: wire up OBIO interrupts to APB pbm via qdev GPIOs

This enables us to remove the static array mapping in the ISA IRQ
handler (and the embedded reference to the APB device) by formalising
the interrupt wiring via the qdev GPIO API.

For more clarity we replace the APB OBIO interrupt numbers with constants
designating the interrupt source, and rename isa_irq_handler() to
ebus_isa_irq_handler().

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Artyom Tarasenko <atar4qemu@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
Mark Cave-Ayland 2017-12-21 07:32:57 +00:00
parent 33c5eb02c4
commit 4b10c8d701
3 changed files with 32 additions and 25 deletions

View file

@ -86,6 +86,7 @@ typedef struct EbusState {
PCIDevice parent_obj;
ISABus *isa_bus;
qemu_irq isa_bus_irqs[ISA_NUM_IRQS];
uint64_t console_serial_base;
MemoryRegion bar0;
MemoryRegion bar1;
@ -211,23 +212,15 @@ typedef struct ResetData {
uint64_t prom_addr;
} ResetData;
static void isa_irq_handler(void *opaque, int n, int level)
static void ebus_isa_irq_handler(void *opaque, int n, int level)
{
static const int isa_irq_to_ivec[16] = {
[1] = 0x29, /* keyboard */
[4] = 0x2b, /* serial */
[6] = 0x27, /* floppy */
[7] = 0x22, /* parallel */
[12] = 0x2a, /* mouse */
};
qemu_irq *irqs = opaque;
int ivec;
EbusState *s = EBUS(opaque);
qemu_irq irq = s->isa_bus_irqs[n];
assert(n < ARRAY_SIZE(isa_irq_to_ivec));
ivec = isa_irq_to_ivec[n];
EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
if (ivec) {
qemu_set_irq(irqs[ivec], level);
/* Pass ISA bus IRQs onto their gpio equivalent */
EBUS_DPRINTF("Set ISA IRQ %d level %d\n", n, level);
if (irq) {
qemu_set_irq(irq, level);
}
}
@ -235,7 +228,6 @@ static void isa_irq_handler(void *opaque, int n, int level)
static void ebus_realize(PCIDevice *pci_dev, Error **errp)
{
EbusState *s = EBUS(pci_dev);
APBState *apb;
DeviceState *dev;
qemu_irq *isa_irq;
DriveInfo *fd[MAX_FD];
@ -248,14 +240,11 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp)
return;
}
apb = APB_DEVICE(object_resolve_path_type("", TYPE_APB, NULL));
if (!apb) {
error_setg(errp, "unable to locate APB PCI host bridge");
return;
}
isa_irq = qemu_allocate_irqs(isa_irq_handler, apb->pbm_irqs, 16);
/* ISA bus */
isa_irq = qemu_allocate_irqs(ebus_isa_irq_handler, s, ISA_NUM_IRQS);
isa_bus_irqs(s->isa_bus, isa_irq);
qdev_init_gpio_out_named(DEVICE(s), s->isa_bus_irqs, "isa-irq",
ISA_NUM_IRQS);
/* Serial ports */
i = 0;
@ -530,6 +519,18 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
hwdef->console_serial_base);
qdev_init_nofail(DEVICE(ebus));
/* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7,
qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6,
qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1,
qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12,
qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ));
qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ));
pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");
memset(&macaddr, 0, sizeof(MACAddr));