From 7b4fdbb60bb53d4c03302e38e613b321163eafb0 Mon Sep 17 00:00:00 2001 From: espes Date: Thu, 29 Aug 2013 16:47:33 +1000 Subject: [PATCH] finally fix up irq routing --- hw/xbox/acpi_xbox.c | 4 +- hw/xbox/acpi_xbox.h | 2 +- hw/xbox/mcpx_aci.c | 17 +--- hw/xbox/mcpx_apu.c | 21 +---- hw/xbox/mcpx_apu.h | 28 ------- hw/xbox/nv2a.c | 15 ++-- hw/xbox/nv2a.h | 2 +- hw/xbox/nvnet.c | 16 +--- hw/xbox/nvnet.h | 27 ------- hw/xbox/xbox.c | 36 +++++---- hw/xbox/xbox_pci.c | 189 ++++++++++++++++++++++++++++---------------- hw/xbox/xbox_pci.h | 22 +++--- 12 files changed, 164 insertions(+), 215 deletions(-) delete mode 100644 hw/xbox/mcpx_apu.h delete mode 100644 hw/xbox/nvnet.h diff --git a/hw/xbox/acpi_xbox.c b/hw/xbox/acpi_xbox.c index 7e4fba08d0..1e2de3cc2d 100644 --- a/hw/xbox/acpi_xbox.c +++ b/hw/xbox/acpi_xbox.c @@ -51,7 +51,7 @@ static void xbox_pm_update_sci_fn(ACPIREGS *regs) #define XBOX_PM_BASE_BAR 0 -void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm/*, qemu_irq sci_irq*/) { +void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm, qemu_irq sci_irq) { memory_region_init(&pm->bar, OBJECT(dev), "xbox-pm-bar", 256); pci_register_bar(dev, XBOX_PM_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO, @@ -62,5 +62,5 @@ void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm/*, qemu_irq sci_irq*/) { acpi_pm1_evt_init(&pm->acpi_regs, xbox_pm_update_sci_fn, &pm->bar); acpi_pm1_cnt_init(&pm->acpi_regs, &pm->bar, 2); - //pm->irq = sci_irq; + pm->irq = sci_irq; } \ No newline at end of file diff --git a/hw/xbox/acpi_xbox.h b/hw/xbox/acpi_xbox.h index 303a119bd9..6c997fde69 100644 --- a/hw/xbox/acpi_xbox.h +++ b/hw/xbox/acpi_xbox.h @@ -29,7 +29,7 @@ typedef struct XBOX_PMRegs { qemu_irq irq; } XBOX_PMRegs; -void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm/*, qemu_irq sci_irq*/); +void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm, qemu_irq sci_irq); //void xbox_pm_iospace_update(MCPX_PMRegs *pm, uint32_t pm_io_base); diff --git a/hw/xbox/mcpx_aci.c b/hw/xbox/mcpx_aci.c index 972b95289a..3253c4038f 100644 --- a/hw/xbox/mcpx_aci.c +++ b/hw/xbox/mcpx_aci.c @@ -21,11 +21,8 @@ #include "hw/pci/pci.h" #include "hw/audio/ac97_int.h" -#include "hw/xbox/mcpx_apu.h" - typedef struct MCPXACIState { PCIDevice dev; - qemu_irq irq; AC97LinkState ac97; @@ -67,7 +64,7 @@ static int mcpx_aci_initfn(PCIDevice *dev) pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); - ac97_common_init(&d->ac97, d->irq, pci_get_address_space(&d->dev)); + ac97_common_init(&d->ac97, dev->irq[0], pci_get_address_space(&d->dev)); return 0; } @@ -97,14 +94,4 @@ static void mcpx_aci_register(void) { type_register_static(&mcpx_aci_info); } -type_init(mcpx_aci_register); - - -void mcpx_aci_init(PCIBus *bus, int devfn, qemu_irq irq) -{ - PCIDevice *dev; - MCPXACIState *d; - dev = pci_create_simple(bus, devfn, "mcpx-aci"); - d = MCPX_ACI_DEVICE(dev); - d->irq = irq; -} +type_init(mcpx_aci_register); \ No newline at end of file diff --git a/hw/xbox/mcpx_apu.c b/hw/xbox/mcpx_apu.c index ee47bc2351..d38761f8b3 100644 --- a/hw/xbox/mcpx_apu.c +++ b/hw/xbox/mcpx_apu.c @@ -20,9 +20,6 @@ #include "hw/i386/pc.h" #include "hw/pci/pci.h" -#include "hw/xbox/mcpx_apu.h" - - #define NV_PAPU_ISTS 0x00001000 # define NV_PAPU_ISTS_GINTSTS (1 << 0) @@ -118,7 +115,6 @@ static const struct { typedef struct MCPXAPUState { PCIDevice dev; - qemu_irq irq; MemoryRegion mmio; @@ -179,11 +175,11 @@ static void update_irq(MCPXAPUState *d) d->regs[NV_PAPU_ISTS] |= NV_PAPU_ISTS_GINTSTS; MCPX_DPRINTF("mcpx irq raise\n"); - qemu_irq_raise(d->irq); + qemu_irq_raise(d->dev.irq[0]); } else { d->regs[NV_PAPU_ISTS] &= ~NV_PAPU_ISTS_GINTSTS; MCPX_DPRINTF("mcpx irq lower\n"); - qemu_irq_lower(d->irq); + qemu_irq_lower(d->dev.irq[0]); } } @@ -461,15 +457,4 @@ static void mcpx_apu_register(void) { type_register_static(&mcpx_apu_info); } -type_init(mcpx_apu_register); - - - -void mcpx_apu_init(PCIBus *bus, int devfn, qemu_irq irq) -{ - PCIDevice *dev; - MCPXAPUState *d; - dev = pci_create_simple(bus, devfn, "mcpx-apu"); - d = MCPX_APU_DEVICE(dev); - d->irq = irq; -} \ No newline at end of file +type_init(mcpx_apu_register); \ No newline at end of file diff --git a/hw/xbox/mcpx_apu.h b/hw/xbox/mcpx_apu.h deleted file mode 100644 index 3daf996e63..0000000000 --- a/hw/xbox/mcpx_apu.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * QEMU MCPX Audio Processing Unit implementation - * - * Copyright (c) 2012 espes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef HW_MCPX_APU_H -#define HW_MCPX_APU_H - -#include "hw/pci/pci.h" - -void mcpx_apu_init(PCIBus *bus, int devfn, qemu_irq irq); -void mcpx_aci_init(PCIBus *bus, int devfn, qemu_irq irq); - -#endif \ No newline at end of file diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 904d394318..b0b80c4382 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -952,9 +952,9 @@ static void update_irq(NV2AState *d) } if (d->pmc.pending_interrupts && d->pmc.enabled_interrupts) { - qemu_irq_raise(d->irq); + qemu_irq_raise(d->dev.irq[0]); } else { - qemu_irq_lower(d->irq); + qemu_irq_lower(d->dev.irq[0]); } } @@ -3904,14 +3904,9 @@ type_init(nv2a_register); -void nv2a_init(PCIBus *bus, int devfn, qemu_irq irq, MemoryRegion *ram) +void nv2a_init(PCIBus *bus, int devfn, MemoryRegion *ram) { - PCIDevice *dev; - NV2AState *d; - dev = pci_create_simple(bus, devfn, "nv2a"); - d = NV2A_DEVICE(dev); - + PCIDevice *dev = pci_create_simple(bus, devfn, "nv2a"); + NV2AState *d = NV2A_DEVICE(dev); nv2a_init_memory(d, ram); - - d->irq = irq; } \ No newline at end of file diff --git a/hw/xbox/nv2a.h b/hw/xbox/nv2a.h index 33a8220e5d..281e4cbbad 100644 --- a/hw/xbox/nv2a.h +++ b/hw/xbox/nv2a.h @@ -20,6 +20,6 @@ #ifndef HW_NV2A_H #define HW_NV2A_H -void nv2a_init(PCIBus *bus, int devfn, qemu_irq irq, MemoryRegion *ram); +void nv2a_init(PCIBus *bus, int devfn, MemoryRegion *ram); #endif \ No newline at end of file diff --git a/hw/xbox/nvnet.c b/hw/xbox/nvnet.c index 3430510255..9708a2a28e 100644 --- a/hw/xbox/nvnet.c +++ b/hw/xbox/nvnet.c @@ -20,8 +20,6 @@ #include "hw/i386/pc.h" #include "hw/pci/pci.h" -#include "hw/xbox/nvnet.h" - #define IOPORT_SIZE 0x8 #define MMIO_SIZE 0x400 @@ -36,8 +34,6 @@ typedef struct NVNetState { PCIDevice dev; - qemu_irq irq; - MemoryRegion mmio, io; } NVNetState; @@ -118,14 +114,4 @@ static void nvnet_register(void) { type_register_static(&nvnet_info); } -type_init(nvnet_register); - - -void nvnet_init(PCIBus *bus, int devfn, qemu_irq irq) -{ - PCIDevice *dev; - NVNetState *d; - dev = pci_create_simple(bus, devfn, "nvnet"); - d = NVNET_DEVICE(dev); - d->irq = irq; -} \ No newline at end of file +type_init(nvnet_register); \ No newline at end of file diff --git a/hw/xbox/nvnet.h b/hw/xbox/nvnet.h deleted file mode 100644 index b93b079a0f..0000000000 --- a/hw/xbox/nvnet.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * QEMU nForce Ethernet Controller implementation - * - * Copyright (c) 2013 espes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef HW_NVNET_H -#define HW_NVNET_H - -#include "hw/pci/pci.h" - -void nvnet_init(PCIBus *bus, int devfn, qemu_irq irq); - -#endif \ No newline at end of file diff --git a/hw/xbox/xbox.c b/hw/xbox/xbox.c index 3da94b3a13..0eae08b59b 100644 --- a/hw/xbox/xbox.c +++ b/hw/xbox/xbox.c @@ -38,9 +38,7 @@ #include "exec/address-spaces.h" #include "hw/xbox/xbox_pci.h" -#include "hw/xbox/nvnet.h" #include "hw/xbox/nv2a.h" -#include "hw/xbox/mcpx_apu.h" #include "hw/xbox/xbox.h" @@ -169,15 +167,13 @@ void xbox_init_common(QEMUMachineInitArgs *args, /* init buses */ - host_bus = xbox_pci_init(gsi, - get_system_memory(), get_system_io(), - pci_memory, ram_memory); - - - /* bridges */ - agp_bus = xbox_agp_init(host_bus); - isa_bus = xbox_lpc_init(host_bus, gsi); - smbus = xbox_smbus_init(host_bus, gsi); + xbox_pci_init(gsi, + get_system_memory(), get_system_io(), + pci_memory, ram_memory, + &host_bus, + &isa_bus, + &smbus, + &agp_bus); /* irq shit */ @@ -211,6 +207,7 @@ void xbox_init_common(QEMUMachineInitArgs *args, pc_cmos_init(ram_size, 0, boot_device, NULL, idebus[0], idebus[1], rtc_state); + /* smbus devices */ uint8_t *eeprom_buf = g_malloc0(256); memcpy(eeprom_buf, default_eeprom, 256); smbus_eeprom_init_single(smbus, 0x54, eeprom_buf); @@ -221,20 +218,25 @@ void xbox_init_common(QEMUMachineInitArgs *args, /* USB */ - pci_create_simple(host_bus, PCI_DEVFN(2, 0), "pci-ohci"); - pci_create_simple(host_bus, PCI_DEVFN(3, 0), "pci-ohci"); + PCIDevice *usb1 = pci_create(host_bus, PCI_DEVFN(3, 0), "pci-ohci"); + qdev_prop_set_uint32(&usb1->qdev, "num-ports", 4); + qdev_init_nofail(&usb1->qdev); + + PCIDevice *usb0 = pci_create(host_bus, PCI_DEVFN(2, 0), "pci-ohci"); + qdev_prop_set_uint32(&usb0->qdev, "num-ports", 4); + qdev_init_nofail(&usb0->qdev); /* Ethernet! */ - nvnet_init(host_bus, PCI_DEVFN(4, 0), gsi[4]); + PCIDevice *nvnet = pci_create_simple(host_bus, PCI_DEVFN(4, 0), "nvnet"); /* APU! */ - mcpx_apu_init(host_bus, PCI_DEVFN(5, 0), gsi[5]); + PCIDevice *apu = pci_create_simple(host_bus, PCI_DEVFN(5, 0), "mcpx-apu"); /* ACI! */ - mcpx_aci_init(host_bus, PCI_DEVFN(6, 0), gsi[6]); + PCIDevice *aci = pci_create_simple(host_bus, PCI_DEVFN(6, 0), "mcpx-aci"); /* GPU! */ - nv2a_init(agp_bus, PCI_DEVFN(0, 0), gsi[3], ram_memory); + nv2a_init(agp_bus, PCI_DEVFN(0, 0), ram_memory); *out_isa_bus = isa_bus; } diff --git a/hw/xbox/xbox_pci.c b/hw/xbox/xbox_pci.c index ca823891ef..7e44fcd385 100644 --- a/hw/xbox/xbox_pci.c +++ b/hw/xbox/xbox_pci.c @@ -59,33 +59,105 @@ +#define XBOX_NUM_INT_IRQS 8 +#define XBOX_NUM_PIRQS 4 +#define XBOX_NUM_PIC_IRQS 16 -PCIBus *xbox_pci_init(qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - MemoryRegion *pci_memory, - MemoryRegion *ram_memory) +#define XBOX_LPC_ACPI_IRQ_ROUT 0x64 +#define XBOX_LPC_PIRQ_ROUT 0x68 +#define XBOX_LPC_INT_IRQ_ROUT 0x6C +static void xbox_lpc_set_irq(void *opaque, int pirq, int level) { - DeviceState *dev; + XBOX_LPCState *lpc = opaque; + + assert(pirq >= 0); + assert(pirq < XBOX_NUM_INT_IRQS + XBOX_NUM_PIRQS); + + int pic_irq = 0; + + if (pirq < XBOX_NUM_INT_IRQS) { + /* devices on the internal bus */ + uint32_t routing = pci_get_long(lpc->dev.config + XBOX_LPC_INT_IRQ_ROUT); + pic_irq = (routing >> (pirq*4)) & 0xF; + + if (pic_irq == 0) { + return; + } + } else { + /* pirqs */ + pirq -= XBOX_NUM_INT_IRQS; + pic_irq = lpc->dev.config[XBOX_LPC_PIRQ_ROUT + pirq]; + } + + if (pic_irq >= XBOX_NUM_PIC_IRQS) { + return; + } + qemu_set_irq(lpc->pic[pic_irq], level); +} + +static int xbox_lpc_map_irq(PCIDevice *pci_dev, int intx) +{ + int slot = PCI_SLOT(pci_dev->devfn); + switch (slot) { + /* devices on the internal bus */ + case 2: return 0; /* usb0 */ + case 3: return 1; /* usb1 */ + case 4: return 2; /* nic */ + case 5: return 3; /* apu */ + case 6: return 4; /* aci */ + case 9: return 6; /* ide */ + + case 30: /* agp bridge -> PIRQC? */ + return XBOX_NUM_INT_IRQS + 2; + default: + /* don't actually know how this should work */ + assert(false); + return XBOX_NUM_INT_IRQS + ((slot + intx) & 3); + } +} + +static void xbox_lpc_set_acpi_irq(void *opaque, int irq_num, int level) +{ + XBOX_LPCState *lpc = opaque; + assert(irq_num == 0 || irq_num == 1); + + uint32_t routing = pci_get_long(lpc->dev.config + XBOX_LPC_ACPI_IRQ_ROUT); + int irq = (routing >> (irq_num*8)) & 0xff; + + if (irq == 0 || irq >= XBOX_NUM_PIC_IRQS) { + return; + } + qemu_set_irq(lpc->pic[irq], level); +} + + + +void xbox_pci_init(qemu_irq *pic, + MemoryRegion *address_space_mem, + MemoryRegion *address_space_io, + MemoryRegion *pci_memory, + MemoryRegion *ram_memory, + PCIBus **out_host_bus, + ISABus **out_isa_bus, + i2c_bus **out_smbus, + PCIBus **out_agp_bus) +{ + DeviceState *host; PCIHostState *host_state; PCIBus *host_bus; PCIDevice *bridge; XBOX_PCIState *bridge_state; /* pci host bus */ - dev = qdev_create(NULL, "xbox-pcihost"); - host_state = PCI_HOST_BRIDGE(dev); + host = qdev_create(NULL, "xbox-pcihost"); + host_state = PCI_HOST_BRIDGE(host); - host_bus = pci_bus_new(dev, NULL, + host_bus = pci_bus_new(host, NULL, pci_memory, address_space_io, 0, TYPE_PCI_BUS); host_state->bus = host_bus; - - //pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, - // PIIX_NUM_PIRQS); - - qdev_init_nofail(dev); + qdev_init_nofail(host); bridge = pci_create_simple_multifunction(host_bus, PCI_DEVFN(0, 0), true, "xbox-pci"); @@ -95,6 +167,7 @@ PCIBus *xbox_pci_init(qemu_irq *pic, bridge_state->system_memory = address_space_mem; /* PCI hole */ + /* TODO: move to xbox-pci init */ memory_region_init_alias(&bridge_state->pci_hole, OBJECT(bridge), "pci-hole", bridge_state->pci_address_space, @@ -104,66 +177,44 @@ PCIBus *xbox_pci_init(qemu_irq *pic, &bridge_state->pci_hole); - return host_bus; -} + /* lpc bridge */ + PCIDevice *lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(1, 0), + true, "xbox-lpc"); + XBOX_LPCState *lpc_state = XBOX_LPC_DEVICE(lpc); + lpc_state->pic = pic; + pci_bus_irqs(host_bus, xbox_lpc_set_irq, xbox_lpc_map_irq, lpc_state, + XBOX_NUM_INT_IRQS + XBOX_NUM_PIRQS); -PCIBus *xbox_agp_init(PCIBus *bus) -{ - PCIDevice *d; - PCIBridge *br; - //DeviceState *qdev; - - /* AGP bus */ - d = pci_create_simple(bus, PCI_DEVFN(30, 0), "xbox-agp"); - if (!d) { - return NULL; - } - - br = PCI_BRIDGE(d); - //qdev = &br->dev.qdev; - //qdev_init_nofail(qdev); - - return pci_bridge_get_sec_bus(br); -} - - -ISABus *xbox_lpc_init(PCIBus *bus, qemu_irq *gsi) -{ - PCIDevice *d; - XBOX_LPCState *s; - //qemu_irq *sci_irq; - - d = pci_create_simple_multifunction(bus, PCI_DEVFN(1, 0), - true, "xbox-lpc"); - - s = XBOX_LPC_DEVICE(d); - - //sci_irq = qemu_allocate_irqs(xbox_set_sci, &s->irq_state, 1); - xbox_pm_init(d, &s->pm /*, sci_irq[0]*/); + qemu_irq *acpi_irq = qemu_allocate_irqs(xbox_lpc_set_acpi_irq, + lpc_state, 2); + xbox_pm_init(lpc, &lpc_state->pm, acpi_irq[0]); //xbox_lpc_reset(&s->dev.qdev); - return s->isa_bus; + + /* smbus */ + PCIDevice *smbus = pci_create_simple_multifunction(host_bus, PCI_DEVFN(1, 1), + true, "xbox-smbus"); + + XBOX_SMBState *smbus_state = XBOX_SMBUS_DEVICE(smbus); + amd756_smbus_init(&smbus->qdev, &smbus_state->smb, acpi_irq[1]); + + + /* AGP bus */ + PCIDevice *agp = pci_create_simple(host_bus, PCI_DEVFN(30, 0), "xbox-agp"); + //qdev = &br->dev.qdev; + //qdev_init_nofail(qdev); + PCIBus *agp_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(agp)); + + + + *out_host_bus = host_bus; + *out_isa_bus = lpc_state->isa_bus; + *out_smbus = smbus_state->smb.smbus; + *out_agp_bus = agp_bus; } -i2c_bus *xbox_smbus_init(PCIBus *bus, qemu_irq *gsi) -{ - PCIDevice *d; - XBOX_SMBState *s; - - d = pci_create_simple_multifunction(bus, PCI_DEVFN(1, 1), - true, "xbox-smbus"); - - s = XBOX_SMBUS_DEVICE(d); - amd756_smbus_init(&d->qdev, &s->smb, gsi[11]); - - return s->smb.smbus; -} - - - - #define XBOX_SMBUS_BASE_BAR 1 static void xbox_smb_ioport_writeb(void *opaque, hwaddr addr, @@ -285,7 +336,7 @@ static void xbox_lpc_reset(DeviceState *dev) if (s->bootrom_size) { /* qemu's memory region shit is actually kinda broken - * Trying to execute off a non-page-aligned memory region - * is fucked, so we can't must map in the bootrom. + * is fucked, so we can't just map in the bootrom. * * We need to be able to disable it at runtime, and * it shouldn't be visible ontop of the bios mirrors. It'll have to @@ -294,7 +345,7 @@ static void xbox_lpc_reset(DeviceState *dev) * Be lazy for now and just write it ontop of the bios. * * (We do this here since loader.c loads roms into memory in a reset - * handler, and here we /should/ be handler after it.) + * handler, and here we /should/ be handled after it.) */ hwaddr bootrom_addr = (uint32_t)(-s->bootrom_size); diff --git a/hw/xbox/xbox_pci.h b/hw/xbox/xbox_pci.h index 73d8b9c768..8cd24670c6 100644 --- a/hw/xbox/xbox_pci.h +++ b/hw/xbox/xbox_pci.h @@ -53,6 +53,7 @@ typedef struct XBOX_LPCState { ISABus *isa_bus; XBOX_PMRegs pm; + qemu_irq *pic; int bootrom_size; uint8_t bootrom_data[512]; @@ -69,17 +70,14 @@ typedef struct XBOX_LPCState { -PCIBus *xbox_pci_init(qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - MemoryRegion *pci_memory, - MemoryRegion *ram_memory); - -PCIBus *xbox_agp_init(PCIBus *bus); - -ISABus *xbox_lpc_init(PCIBus *bus, qemu_irq *gsi); - -i2c_bus *xbox_smbus_init(PCIBus *bus, qemu_irq *gsi); - +void xbox_pci_init(qemu_irq *pic, + MemoryRegion *address_space_mem, + MemoryRegion *address_space_io, + MemoryRegion *pci_memory, + MemoryRegion *ram_memory, + PCIBus **out_host_bus, + ISABus **out_isa_bus, + i2c_bus **out_smbus, + PCIBus **out_agp_bus); #endif \ No newline at end of file