From 71c5309318b45a6836d6312386c66eef230ede04 Mon Sep 17 00:00:00 2001 From: espes Date: Thu, 25 Oct 2012 10:42:05 +1100 Subject: [PATCH] xbox: smbus irq, and make pmbase a pci bar, since that's what the available bios uses --- hw/acpi_mcpx.c | 40 +++++++++++++++------- hw/acpi_mcpx.h | 6 ++-- hw/amd_smbus.c | 92 ++++++++++++++++++++++++++++++++------------------ hw/amd_smbus.h | 4 ++- hw/xbox.c | 9 +++-- hw/xbox_pci.c | 32 ++++++++++-------- hw/xbox_pci.h | 9 +++-- 7 files changed, 118 insertions(+), 74 deletions(-) diff --git a/hw/acpi_mcpx.c b/hw/acpi_mcpx.c index a17c9a3ebd..1e074346fe 100644 --- a/hw/acpi_mcpx.c +++ b/hw/acpi_mcpx.c @@ -30,7 +30,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "acpi.h" - +#include "xbox_pci.h" #include "acpi_mcpx.h" //#define DEBUG @@ -55,10 +55,11 @@ static void mcpx_pm_update_sci_gn(ACPIREGS *regs) #define MCPX_PMIO_PM1_CNT 0x4 #define MCPX_PMIO_PM_TMR 0x8 -static void mcpx_pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, - uint64_t val) +static void mcpx_pm_ioport_write(void *opaque, + target_phys_addr_t addr, + uint64_t val, unsigned size) { - MCPX_PMRegs *pm = container_of(ioport, MCPX_PMRegs, ioport); + MCPX_PMRegs *pm = opaque; switch (addr) { case MCPX_PMIO_PM1_STS: @@ -79,11 +80,12 @@ static void mcpx_pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, (unsigned int)addr, (unsigned int)val); } -static void mcpx_pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width, - uint64_t *data) +static uint64_t mcpx_pm_ioport_read(void *opaque, + target_phys_addr_t addr, + unsigned size) { - MCPX_PMRegs *pm = container_of(ioport, MCPX_PMRegs, ioport); - uint32_t val; + MCPX_PMRegs *pm = opaque; + uint64_t val; switch (addr) { case MCPX_PMIO_PM1_STS: @@ -104,15 +106,19 @@ static void mcpx_pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width, } MCPX_DPRINTF("PM: read port=0x%04x val=0x%04x\n", (unsigned int)addr, (unsigned int)val); - *data = val; + return val; } -static const IORangeOps mcpx_iorange_ops = { +static const MemoryRegionOps mcpx_pm_ops = { .read = mcpx_pm_ioport_read, .write = mcpx_pm_ioport_write, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, }; - +#if 0 void mcpx_pm_iospace_update(MCPX_PMRegs *pm, uint32_t pm_io_base) { MCPX_DPRINTF("PM: iospace update to 0x%x\n", pm_io_base); @@ -122,8 +128,18 @@ void mcpx_pm_iospace_update(MCPX_PMRegs *pm, uint32_t pm_io_base) { ioport_register(&pm->ioport); } } +#endif + + +#define MCPX_PM_BASE_BAR 0 + +void mcpx_pm_init(PCIDevice *dev, MCPX_PMRegs *pm/*, qemu_irq sci_irq*/) { + + memory_region_init_io(&pm->bar, &mcpx_pm_ops, + pm, "mcpx-pm-bar", 256); + pci_register_bar(dev, MCPX_PM_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO, + &pm->bar); -void mcpx_pm_init(MCPX_PMRegs *pm/*, qemu_irq sci_irq*/) { acpi_pm_tmr_init(&pm->acpi_regs, mcpx_pm_update_sci_gn); acpi_pm1_cnt_init(&pm->acpi_regs); //acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); diff --git a/hw/acpi_mcpx.h b/hw/acpi_mcpx.h index 021400ae60..c249f941e4 100644 --- a/hw/acpi_mcpx.h +++ b/hw/acpi_mcpx.h @@ -23,14 +23,14 @@ #include "acpi.h" typedef struct MCPX_PMRegs { - IORange ioport; + MemoryRegion bar; ACPIREGS acpi_regs; qemu_irq irq; } MCPX_PMRegs; -void mcpx_pm_init(MCPX_PMRegs *pm /*, qemu_irq sci_irq*/); -void mcpx_pm_iospace_update(MCPX_PMRegs *pm, uint32_t pm_io_base); +void mcpx_pm_init(PCIDevice *dev, MCPX_PMRegs *pm/*, qemu_irq sci_irq*/); +//void mcpx_pm_iospace_update(MCPX_PMRegs *pm, uint32_t pm_io_base); #endif \ No newline at end of file diff --git a/hw/amd_smbus.c b/hw/amd_smbus.c index c644f6a7c5..c619f45470 100644 --- a/hw/amd_smbus.c +++ b/hw/amd_smbus.c @@ -4,45 +4,48 @@ #include "smbus.h" /* AMD756 SMBus address offsets */ -#define SMB_ADDR_OFFSET 0xE0 -#define SMB_IOSIZE 16 -#define SMB_GLOBAL_STATUS 0x0 -#define SMB_GLOBAL_ENABLE 0x2 -#define SMB_HOST_ADDRESS 0x4 -#define SMB_HOST_DATA 0x6 -#define SMB_HOST_COMMAND 0x8 -#define SMB_HOST_BLOCK_DATA 0x9 -#define SMB_HAS_DATA 0xA -#define SMB_HAS_DEVICE_ADDRESS 0xC -#define SMB_HAS_HOST_ADDRESS 0xE -#define SMB_SNOOP_ADDRESS 0xF +#define SMB_ADDR_OFFSET 0xE0 +#define SMB_IOSIZE 16 + +#define SMB_GLOBAL_STATUS 0x0 +#define SMB_GLOBAL_ENABLE 0x2 +#define SMB_HOST_ADDRESS 0x4 +#define SMB_HOST_DATA 0x6 +#define SMB_HOST_COMMAND 0x8 +#define SMB_HOST_BLOCK_DATA 0x9 +#define SMB_HAS_DATA 0xA +#define SMB_HAS_DEVICE_ADDRESS 0xC +#define SMB_HAS_HOST_ADDRESS 0xE +#define SMB_SNOOP_ADDRESS 0xF /* AMD756 constants */ -#define AMD756_QUICK 0x00 -#define AMD756_BYTE 0x01 -#define AMD756_BYTE_DATA 0x02 -#define AMD756_WORD_DATA 0x03 -#define AMD756_PROCESS_CALL 0x04 -#define AMD756_BLOCK_DATA 0x05 +#define AMD756_QUICK 0x00 +#define AMD756_BYTE 0x01 +#define AMD756_BYTE_DATA 0x02 +#define AMD756_WORD_DATA 0x03 +#define AMD756_PROCESS_CALL 0x04 +#define AMD756_BLOCK_DATA 0x05 /* SMBUS event = I/O 28-29 bit 11 see E0 for the status bits and enabled in E2 */ -#define GS_ABRT_STS (1 << 0) -#define GS_COL_STS (1 << 1) -#define GS_PRERR_STS (1 << 2) -#define GS_HST_STS (1 << 3) -#define GS_HCYC_STS (1 << 4) -#define GS_TO_STS (1 << 5) -#define GS_SMB_STS (1 << 11) +#define GS_ABRT_STS (1 << 0) +#define GS_COL_STS (1 << 1) +#define GS_PRERR_STS (1 << 2) +#define GS_HST_STS (1 << 3) +#define GS_HCYC_STS (1 << 4) +#define GS_TO_STS (1 << 5) +#define GS_SMB_STS (1 << 11) -#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ - GS_HCYC_STS | GS_TO_STS ) +#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ + GS_HCYC_STS | GS_TO_STS ) -#define GE_CYC_TYPE_MASK (7) -#define GE_HOST_STC (1 << 3) -#define GE_ABORT (1 << 5) +#define GE_CYC_TYPE_MASK (7) +#define GE_HOST_STC (1 << 3) + +#define GE_HCYC_EN (1 << 4) +#define GE_ABORT (1 << 5) @@ -118,7 +121,20 @@ void amd756_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val); switch(addr) { case SMB_GLOBAL_STATUS: - //s->smb_stat = 0; + + if (s->irq) { + /* Raise an irq if interrupts are enabled and a new + * status is being set */ + if ((s->smb_ctl & GE_HCYC_EN) + && ((val & GS_CLEAR_STS) + & (~(s->smb_stat & GS_CLEAR_STS)))) { + + qemu_irq_raise(s->irq); + } else { + qemu_irq_lower(s->irq); + } + } + if (val & GS_CLEAR_STS) { s->smb_stat = 0; s->smb_index = 0; @@ -135,8 +151,16 @@ void amd756_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) s->smb_ctl = val; if (val & GE_ABORT) s->smb_stat |= GS_ABRT_STS; - if (val & GE_HOST_STC) + if (val & GE_HOST_STC) { amd756_smb_transaction(s); + + if (s->irq + && (val & GE_HCYC_EN) + && (s->smb_stat & GS_CLEAR_STS)) { + qemu_irq_raise(s->irq); + } + } + break; case SMB_HOST_COMMAND: s->smb_cmd = val; @@ -199,8 +223,10 @@ uint32_t amd756_smb_ioport_readb(void *opaque, uint32_t addr) return val; } -void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb) +void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb, qemu_irq irq) { smb->smbus = i2c_init_bus(parent, "i2c"); smb->smb_stat = 0; + + smb->irq = irq; } \ No newline at end of file diff --git a/hw/amd_smbus.h b/hw/amd_smbus.h index 9a4d8ad390..6bf535798c 100644 --- a/hw/amd_smbus.h +++ b/hw/amd_smbus.h @@ -12,9 +12,11 @@ typedef struct AMD756SMBus { //uint8_t smb_data1; uint8_t smb_data[32]; uint8_t smb_index; + + qemu_irq irq; } AMD756SMBus; -void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb); +void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb, qemu_irq irq); void amd756_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val); uint32_t amd756_smb_ioport_readb(void *opaque, uint32_t addr); diff --git a/hw/xbox.c b/hw/xbox.c index 2f91def8cb..489792ef17 100644 --- a/hw/xbox.c +++ b/hw/xbox.c @@ -183,7 +183,6 @@ static void xbox_init(QEMUMachineInitArgs *args) ISADevice *rtc_state; ISADevice *pit; - DeviceState *xboxpci_host; i2c_bus *smbus; PCIBus *agp_bus; @@ -210,15 +209,15 @@ static void xbox_init(QEMUMachineInitArgs *args) /* init buses */ - host_bus = xbox_pci_init(&xboxpci_host, gsi, + host_bus = xbox_pci_init(gsi, system_memory, system_io, pci_memory, ram_memory); /* bridges */ - agp_bus = xbox_agp_init(xboxpci_host, host_bus); - isa_bus = mcpx_lpc_init(xboxpci_host, host_bus); - smbus = mcpx_smbus_init(xboxpci_host, host_bus); + agp_bus = xbox_agp_init(host_bus); + isa_bus = mcpx_lpc_init(host_bus, gsi); + smbus = mcpx_smbus_init(host_bus, gsi); /* irq shit */ diff --git a/hw/xbox_pci.c b/hw/xbox_pci.c index 3c9a77a24c..7710edca49 100644 --- a/hw/xbox_pci.c +++ b/hw/xbox_pci.c @@ -48,7 +48,7 @@ */ -//#define DEBUG +#define DEBUG #ifdef DEBUG # define XBOXPCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) @@ -60,8 +60,7 @@ -PCIBus *xbox_pci_init(DeviceState **xbox_pci_hostp, - qemu_irq *pic, +PCIBus *xbox_pci_init(qemu_irq *pic, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, MemoryRegion *pci_memory, @@ -105,12 +104,11 @@ PCIBus *xbox_pci_init(DeviceState **xbox_pci_hostp, &bridge->pci_hole); - *xbox_pci_hostp = dev; return hostBus; } -PCIBus *xbox_agp_init(DeviceState *host, PCIBus *bus) +PCIBus *xbox_agp_init(PCIBus *bus) { PCIDevice *d; PCIBridge *br; @@ -130,7 +128,7 @@ PCIBus *xbox_agp_init(DeviceState *host, PCIBus *bus) } -ISABus *mcpx_lpc_init(DeviceState *host, PCIBus *bus) +ISABus *mcpx_lpc_init(PCIBus *bus, qemu_irq *gsi) { PCIDevice *d; MCPX_LPCState *s; @@ -142,14 +140,14 @@ ISABus *mcpx_lpc_init(DeviceState *host, PCIBus *bus) s = MCPX_LPC_DEVICE(d); //sci_irq = qemu_allocate_irqs(mcpx_set_sci, &s->irq_state, 1); - mcpx_pm_init(&s->pm /*, sci_irq[0]*/); + mcpx_pm_init(d, &s->pm /*, sci_irq[0]*/); //mcpx_lpc_reset(&s->dev.qdev); return s->isa_bus; } -i2c_bus *mcpx_smbus_init(DeviceState *host, PCIBus *bus) +i2c_bus *mcpx_smbus_init(PCIBus *bus, qemu_irq *gsi) { PCIDevice *d; MCPX_SMBState *s; @@ -158,6 +156,7 @@ i2c_bus *mcpx_smbus_init(DeviceState *host, PCIBus *bus) true, "mcpx-smbus"); s = MCPX_SMBUS_DEVICE(d); + amd756_smbus_init(&d->qdev, &s->smb, gsi[11]); return s->smb.smbus; } @@ -203,7 +202,6 @@ static int mcpx_smbus_initfn(PCIDevice *dev) s, "mcpx-smbus-bar", 32); pci_register_bar(dev, MCPX_SMBUS_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO, &s->smb_bar); - amd756_smbus_init(&dev->qdev, &s->smb); return 0; } @@ -235,9 +233,6 @@ static const TypeInfo mcpx_smbus_info = { -#define MCPX_LPC_PMBASE 0x84 -#define MCPX_LPC_PMBASE_ADDRESS_MASK 0xff00 -#define MCPX_LPC_PMBASE_DEFAULT 0x1 static int mcpx_lpc_initfn(PCIDevice *d) { @@ -250,6 +245,12 @@ static int mcpx_lpc_initfn(PCIDevice *d) return 0; } +#if 0 +/* Xbox 1.1 uses a config register instead of a bar to set the pm base address */ +#define MCPX_LPC_PMBASE 0x84 +#define MCPX_LPC_PMBASE_ADDRESS_MASK 0xff00 +#define MCPX_LPC_PMBASE_DEFAULT 0x1 + static void mcpx_lpc_pmbase_update(MCPX_LPCState *s) { uint32_t pm_io_base = pci_get_long(s->dev.config + MCPX_LPC_PMBASE); @@ -290,6 +291,7 @@ static const VMStateDescription vmstate_mcpx_lpc = { .version_id = 1, .post_load = mcpx_lpc_post_load, }; +#endif static void mcpx_lpc_class_init(ObjectClass *klass, void *data) { @@ -298,7 +300,7 @@ static void mcpx_lpc_class_init(ObjectClass *klass, void *data) k->no_hotplug = 1; k->init = mcpx_lpc_initfn; - k->config_write = mcpx_lpc_config_write; + //k->config_write = mcpx_lpc_config_write; k->vendor_id = PCI_VENDOR_ID_NVIDIA; k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_LPC; k->revision = 212; @@ -306,8 +308,8 @@ static void mcpx_lpc_class_init(ObjectClass *klass, void *data) dc->desc = "nForce LPC Bridge"; dc->no_user = 1; - dc->reset = mcpx_lpc_reset; - dc->vmsd = &vmstate_mcpx_lpc; + //dc->reset = mcpx_lpc_reset; + //dc->vmsd = &vmstate_mcpx_lpc; } static const TypeInfo mcpx_lpc_info = { diff --git a/hw/xbox_pci.h b/hw/xbox_pci.h index 1b102bed2f..af058ddec8 100644 --- a/hw/xbox_pci.h +++ b/hw/xbox_pci.h @@ -65,18 +65,17 @@ typedef struct MCPX_LPCState { -PCIBus *xbox_pci_init(DeviceState **xbox_pci_hostp, - qemu_irq *pic, +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(DeviceState *host, PCIBus *bus); +PCIBus *xbox_agp_init(PCIBus *bus); -ISABus *mcpx_lpc_init(DeviceState *host, PCIBus *bus); +ISABus *mcpx_lpc_init(PCIBus *bus, qemu_irq *gsi); -i2c_bus *mcpx_smbus_init(DeviceState *host, PCIBus *bus); +i2c_bus *mcpx_smbus_init(PCIBus *bus, qemu_irq *gsi); #endif \ No newline at end of file