finally fix up irq routing

This commit is contained in:
espes 2013-08-29 16:47:33 +10:00
parent 2c88de84af
commit 7b4fdbb60b
12 changed files with 164 additions and 215 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
type_init(mcpx_apu_register);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
type_init(nvnet_register);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef HW_NVNET_H
#define HW_NVNET_H
#include "hw/pci/pci.h"
void nvnet_init(PCIBus *bus, int devfn, qemu_irq irq);
#endif

View File

@ -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;
}

View File

@ -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);

View File

@ -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