diff --git a/hw/acpi_mcpx.c b/hw/acpi_mcpx.c
new file mode 100644
index 0000000000..7f5e39474f
--- /dev/null
+++ b/hw/acpi_mcpx.c
@@ -0,0 +1,132 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+ /*
+ * Copyright (C) 2012 espes
+ *
+ * Based on acpi.c, acpi_ich9.c, acpi_piix4.c
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "acpi.h"
+
+#include "acpi_mcpx.h"
+
+#define DEBUG
+
+#ifdef DEBUG
+# define MCPX_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define MCPX_DPRINTF(format, ...) do { } while (0)
+#endif
+
+
+
+static void mcpx_pm_update_sci_gn(ACPIREGS *regs)
+{
+ MCPX_PMRegs *pm = container_of(regs, MCPX_PMRegs, acpi_regs);
+ //pm_update_sci(pm);
+}
+
+
+#define MCPX_PMIO_PM1_STS 0x0
+#define MCPX_PMIO_PM1_EN 0x2
+#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)
+{
+ MCPX_PMRegs *pm = container_of(ioport, MCPX_PMRegs, ioport);
+
+ switch (addr) {
+ case MCPX_PMIO_PM1_STS:
+ acpi_pm1_evt_write_sts(&pm->acpi_regs, val);
+ //pm_update_sci(pm);
+ break;
+ case MCPX_PMIO_PM1_EN:
+ pm->acpi_regs.pm1.evt.en = val;
+ //pm_update_sci(pm);
+ break;
+ case MCPX_PMIO_PM1_CNT:
+ acpi_pm1_cnt_write(&pm->acpi_regs, val, 0);
+ break;
+ default:
+ break;
+ }
+ MCPX_DPRINTF("PM: write port=0x%04x val=0x%04x\n",
+ (unsigned int)addr, (unsigned int)val);
+}
+
+static void mcpx_pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width,
+ uint64_t *data)
+{
+ MCPX_PMRegs *pm = container_of(ioport, MCPX_PMRegs, ioport);
+ uint32_t val;
+
+ switch (addr) {
+ case MCPX_PMIO_PM1_STS:
+ val = acpi_pm1_evt_get_sts(&pm->acpi_regs);
+ break;
+ case MCPX_PMIO_PM1_EN:
+ val = pm->acpi_regs.pm1.evt.en;
+ break;
+ case MCPX_PMIO_PM1_CNT:
+ val = pm->acpi_regs.pm1.cnt.cnt;
+ break;
+ case MCPX_PMIO_PM_TMR:
+ val = acpi_pm_tmr_get(&pm->acpi_regs);
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ MCPX_DPRINTF("PM: read port=0x%04x val=0x%04x\n",
+ (unsigned int)addr, (unsigned int)val);
+ *data = val;
+}
+
+static const IORangeOps mcpx_iorange_ops = {
+ .read = mcpx_pm_ioport_read,
+ .write = mcpx_pm_ioport_write,
+};
+
+
+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);
+
+ //Disabled when 0
+ if (pm_io_base != 0) {
+ iorange_init(&pm->ioport, &mcpx_iorange_ops, pm_io_base, 256);
+ ioport_register(&pm->ioport);
+ }
+}
+
+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);
+
+ //pm->irq = sci_irq;
+}
\ No newline at end of file
diff --git a/hw/acpi_mcpx.h b/hw/acpi_mcpx.h
new file mode 100644
index 0000000000..021400ae60
--- /dev/null
+++ b/hw/acpi_mcpx.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU MCPX PM Emulation
+ *
+ * Copyright (c) 2012 espes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ */
+
+#ifndef HW_ACPI_MCPX_H
+#define HW_ACPI_MCPX_H
+
+#include "acpi.h"
+
+typedef struct MCPX_PMRegs {
+ IORange ioport;
+ 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);
+
+
+#endif
\ No newline at end of file
diff --git a/hw/amd_smbus.c b/hw/amd_smbus.c
new file mode 100644
index 0000000000..301a008234
--- /dev/null
+++ b/hw/amd_smbus.c
@@ -0,0 +1,206 @@
+#include "hw.h"
+#include "pc.h"
+#include "amd_smbus.h"
+#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
+
+/* 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
+
+/*
+ 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_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 DEBUG
+
+#ifdef DEBUG
+# define SMBUS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define SMBUS_DPRINTF(format, ...) do { } while (0)
+#endif
+
+static void amd756_smb_transaction(AMD756SMBus *s)
+{
+ uint8_t prot = s->smb_ctl & GE_CYC_TYPE_MASK;
+ uint8_t read = s->smb_addr & 0x01;
+ uint8_t cmd = s->smb_cmd;
+ uint8_t addr = (s->smb_addr >> 1) & 0x7f;
+ i2c_bus *bus = s->smbus;
+
+ SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+ switch(prot) {
+ case AMD756_QUICK:
+ smbus_quick_command(bus, addr, read);
+ break;
+ case AMD756_BYTE:
+ if (read) {
+ s->smb_data0 = smbus_receive_byte(bus, addr);
+ } else {
+ smbus_send_byte(bus, addr, cmd);
+ }
+ break;
+ case AMD756_BYTE_DATA:
+ if (read) {
+ s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+ } else {
+ smbus_write_byte(bus, addr, cmd, s->smb_data0);
+ }
+ break;
+ case AMD756_WORD_DATA:
+ if (read) {
+ uint16_t val;
+ val = smbus_read_word(bus, addr, cmd);
+ s->smb_data0 = val;
+ //s->smb_data1 = val >> 8;
+ } else {
+ smbus_write_word(bus, addr, cmd, s->smb_data0);
+ }
+ break;
+ case AMD756_BLOCK_DATA:
+ if (read) {
+ s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+ } else {
+ smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ s->smb_stat |= GS_HCYC_STS;
+
+ return;
+
+
+ error:
+ s->smb_stat |= GS_PRERR_STS;
+}
+
+void amd756_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ AMD756SMBus *s = opaque;
+ addr &= 0x3f;
+ SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+ switch(addr) {
+ case SMB_GLOBAL_STATUS:
+ //s->smb_stat = 0;
+ if (val & GS_CLEAR_STS) {
+ s->smb_stat = 0;
+ s->smb_index = 0;
+ } else if (val & GS_HCYC_STS) {
+ s->smb_stat = GS_HCYC_STS;
+ s->smb_index = 0;
+ } else {
+ s->smb_stat = GS_HCYC_STS;
+ s->smb_index = 0;
+ }
+
+ break;
+ case SMB_GLOBAL_ENABLE:
+ s->smb_ctl = val;
+ if (val & GE_ABORT)
+ s->smb_stat |= GS_ABRT_STS;
+ if (val & GE_HOST_STC)
+ amd756_smb_transaction(s);
+ break;
+ case SMB_HOST_COMMAND:
+ s->smb_cmd = val;
+ break;
+ case SMB_HOST_ADDRESS:
+ s->smb_addr = val;
+ break;
+ case SMB_HOST_DATA:
+ s->smb_data0 = val;
+ break;
+ /*case SMBHSTDAT1:
+ s->smb_data1 = val;
+ break;*/
+ case SMB_HOST_BLOCK_DATA:
+ s->smb_data[s->smb_index++] = val;
+ if (s->smb_index > 31)
+ s->smb_index = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+uint32_t amd756_smb_ioport_readb(void *opaque, uint32_t addr)
+{
+ AMD756SMBus *s = opaque;
+ uint32_t val;
+
+ addr &= 0x3f;
+ switch(addr) {
+ case SMB_GLOBAL_STATUS:
+ val = s->smb_stat;
+ break;
+ case SMB_GLOBAL_ENABLE:
+ //s->smb_index = 0;
+ val = s->smb_ctl & 0x1f;
+ break;
+ case SMB_HOST_COMMAND:
+ val = s->smb_cmd;
+ break;
+ case SMB_HOST_ADDRESS:
+ val = s->smb_addr;
+ break;
+ case SMB_HOST_DATA:
+ val = s->smb_data0;
+ break;
+ /*case SMBHSTDAT1:
+ val = s->smb_data1;
+ break;*/
+ case SMB_HOST_BLOCK_DATA:
+ val = s->smb_data[s->smb_index++];
+ if (s->smb_index > 31)
+ s->smb_index = 0;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ SMBUS_DPRINTF("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+ return val;
+}
+
+void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb)
+{
+ smb->smbus = i2c_init_bus(parent, "i2c");
+ smb->smb_stat = 0;
+}
\ No newline at end of file
diff --git a/hw/amd_smbus.h b/hw/amd_smbus.h
new file mode 100644
index 0000000000..9a4d8ad390
--- /dev/null
+++ b/hw/amd_smbus.h
@@ -0,0 +1,21 @@
+#ifndef AMD_SMBUS_H
+#define AMD_SMBUS_H
+
+typedef struct AMD756SMBus {
+ i2c_bus *smbus;
+
+ uint8_t smb_stat;
+ uint8_t smb_ctl;
+ uint8_t smb_cmd;
+ uint8_t smb_addr;
+ uint8_t smb_data0;
+ //uint8_t smb_data1;
+ uint8_t smb_data[32];
+ uint8_t smb_index;
+} AMD756SMBus;
+
+void amd756_smbus_init(DeviceState *parent, AMD756SMBus *smb);
+void amd756_smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
+uint32_t amd756_smb_ioport_readb(void *opaque, uint32_t addr);
+
+#endif /* !AMD_SMBUS_H */
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 8c764bbfef..0a34a48278 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -12,4 +12,6 @@ obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
obj-y += kvm/
obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
+obj-$(CONFIG_XBOX) += xbox.o xbox_pci.o acpi_mcpx.o amd_smbus.o nv2a.o smbus_pic16lc.o smbus_cx25871.o smbus_adm1032.o
+
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/nv2a.c b/hw/nv2a.c
new file mode 100644
index 0000000000..a352aa984d
--- /dev/null
+++ b/hw/nv2a.c
@@ -0,0 +1,569 @@
+/*
+ * QEMU Geforce NV2A implementation
+ *
+ * Copyright (c) 2012 espes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw.h"
+#include "pc.h"
+#include "console.h"
+#include "pci.h"
+#include "vga_int.h"
+
+#include "nv2a.h"
+
+#define DEBUG_NV2A
+#ifdef DEBUG_NV2A
+# define NV2A_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define NV2A_DPRINTF(format, ...) do { } while (0)
+#endif
+
+
+#define NV_NUM_BLOCKS 20
+#define NV_PMC 0 /* card master control */
+#define NV_PBUS 1 /* bus control */
+#define NV_PFIFO 2 /* MMIO and DMA FIFO submission to PGRAPH and VPE */
+#define NV_PFIFO_CACHE 3
+#define NV_PRMA 4 /* access to BAR0/BAR1 from real mode */
+#define NV_PVIDEO 5 /* video overlay */
+#define NV_PTIMER 6 /* time measurement and time-based alarms */
+#define NV_PCOUNTER 7 /* performance monitoring counters */
+#define NV_PVPE 8 /* MPEG2 decoding engine */
+#define NV_PTV 9 /* TV encoder */
+#define NV_PRMFB 10 /* aliases VGA memory window */
+#define NV_PRMVIO 11 /* aliases VGA sequencer and graphics controller registers */
+#define NV_PSTRAPS 12 /* straps readout / override */
+#define NV_PGRAPH 13 /* accelerated 2d/3d drawing engine */
+#define NV_PCRTC 14 /* more CRTC controls */
+#define NV_PRMCIO 15 /* aliases VGA CRTC and attribute controller registers */
+#define NV_PRAMDAC 16 /* RAMDAC, cursor, and PLL control */
+#define NV_PRMDIO 17 /* aliases VGA palette registers */
+#define NV_PRAMIN 18 /* RAMIN access */
+#define NV_USER 19 /* PFIFO MMIO and DMA submission area */
+
+
+typedef struct NV2AState {
+ PCIDevice dev;
+ VGACommonState vga;
+
+ MemoryRegion vram;
+ MemoryRegion mmio;
+
+ MemoryRegion block_mmio[NV_NUM_BLOCKS];
+} NV2AState;
+
+
+
+
+static uint64_t nv2a_pmc_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PMC: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pmc_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PMC: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pbus_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PBUS: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pbus_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PBUS: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pfifo_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PFIFO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pfifo_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PFIFO: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_prma_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMA: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_prma_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMA: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pvideo_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PVIDEO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pvideo_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PVIDEO: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_ptimer_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PTIMER: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_ptimer_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PTIMER: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pcounter_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PCOUNTER: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pcounter_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PCOUNTER: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pvpe_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PVPE: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pvpe_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PVPE: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_ptv_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PTV: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_ptv_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PTV: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_prmfb_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMFB: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_prmfb_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMFB: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_prmvio_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMVIO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_prmvio_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMVIO: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pstraps_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PSTRAPS: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pstraps_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PSTRAPS: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pgraph_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PGRAPH: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pgraph_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PGRAPH: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pcrtc_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PCRTC: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pcrtc_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PCRTC: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_prmcio_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMCIO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_prmcio_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMCIO: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pramdac_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRAMDAC: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pramdac_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRAMDAC: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_prmdio_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMDIO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_prmdio_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRMDIO: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_pramin_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRAMIN: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_pramin_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a PRAMIN: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+static uint64_t nv2a_user_read(void *opaque,
+ target_phys_addr_t addr, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a USER: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nv2a_user_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
+{
+ NV2A_DPRINTF("nv2a USER: [0x%llx] = 0x%02llx\n", addr, val);
+}
+
+
+
+
+typedef struct NV2ABlockInfo {
+ const char* name;
+ target_phys_addr_t offset;
+ uint64_t size;
+ MemoryRegionOps ops;
+} NV2ABlockInfo;
+
+static const struct NV2ABlockInfo blocktable[] = {
+ [ NV_PMC ] = {
+ .name = "PMC",
+ .offset = 0x000000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pmc_read,
+ .write = nv2a_pmc_write,
+ },
+ },
+ [ NV_PBUS ] = {
+ .name = "PBUS",
+ .offset = 0x001000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pbus_read,
+ .write = nv2a_pbus_write,
+ },
+ },
+ [ NV_PFIFO ] = {
+ .name = "PFIFO",
+ .offset = 0x002000,
+ .size = 0x002000,
+ .ops = {
+ .read = nv2a_pfifo_read,
+ .write = nv2a_pfifo_write,
+ },
+ },
+ [ NV_PRMA ] = {
+ .name = "PRMA",
+ .offset = 0x007000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_prma_read,
+ .write = nv2a_prma_write,
+ },
+ },
+ [ NV_PVIDEO ] = {
+ .name = "PVIDEO",
+ .offset = 0x008000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pvideo_read,
+ .write = nv2a_pvideo_write,
+ },
+ },
+ [ NV_PTIMER ] = {
+ .name = "PTIMER",
+ .offset = 0x009000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_ptimer_read,
+ .write = nv2a_ptimer_write,
+ },
+ },
+ [ NV_PCOUNTER ] = {
+ .name = "PCOUNTER",
+ .offset = 0x00a000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pcounter_read,
+ .write = nv2a_pcounter_write,
+ },
+ },
+ [ NV_PVPE ] = {
+ .name = "PVPE",
+ .offset = 0x00b000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pvpe_read,
+ .write = nv2a_pvpe_write,
+ },
+ },
+ [ NV_PTV ] = {
+ .name = "PTV",
+ .offset = 0x00d000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_ptv_read,
+ .write = nv2a_ptv_write,
+ },
+ },
+ [ NV_PRMFB ] = {
+ .name = "PRMFB",
+ .offset = 0x0a0000,
+ .size = 0x020000,
+ .ops = {
+ .read = nv2a_prmfb_read,
+ .write = nv2a_prmfb_write,
+ },
+ },
+ [ NV_PRMVIO ] = {
+ .name = "PRMVIO",
+ .offset = 0x0c0000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_prmvio_read,
+ .write = nv2a_prmvio_write,
+ },
+ },
+ [ NV_PSTRAPS ] = {
+ .name = "PSTRAPS",
+ .offset = 0x101000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pstraps_read,
+ .write = nv2a_pstraps_write,
+ },
+ },
+ [ NV_PGRAPH ] = {
+ .name = "PGRAPH",
+ .offset = 0x400000,
+ .size = 0x002000,
+ .ops = {
+ .read = nv2a_pgraph_read,
+ .write = nv2a_pgraph_write,
+ },
+ },
+ [ NV_PCRTC ] = {
+ .name = "PCRTC",
+ .offset = 0x600000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pcrtc_read,
+ .write = nv2a_pcrtc_write,
+ },
+ },
+ [ NV_PRMCIO ] = {
+ .name = "PRMCIO",
+ .offset = 0x601000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_prmcio_read,
+ .write = nv2a_prmcio_write,
+ },
+ },
+ [ NV_PRAMDAC ] = {
+ .name = "PRAMDAC",
+ .offset = 0x680000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_pramdac_read,
+ .write = nv2a_pramdac_write,
+ },
+ },
+ [ NV_PRMDIO ] = {
+ .name = "PRMDIO",
+ .offset = 0x681000,
+ .size = 0x001000,
+ .ops = {
+ .read = nv2a_prmdio_read,
+ .write = nv2a_prmdio_write,
+ },
+ },
+ [ NV_PRAMIN ] = {
+ .name = "PRAMIN",
+ .offset = 0x700000,
+ .size = 0x100000,
+ .ops = {
+ .read = nv2a_pramin_read,
+ .write = nv2a_pramin_write,
+ },
+ },
+ [ NV_USER ] = {
+ .name = "USER",
+ .offset = 0x800000,
+ .size = 0x800000,
+ .ops = {
+ .read = nv2a_user_read,
+ .write = nv2a_user_write,
+ },
+ },
+};
+
+
+
+
+static int nv2a_initfn(PCIDevice *dev)
+{
+ int i;
+ NV2AState *d = DO_UPCAST(NV2AState, dev, dev);
+ //uint8_t *pci_conf = d->dev.config;
+
+ /* setup legacy VGA */
+ //d->vga.vram_size_mb = 16;
+ //vga_common_init(&d->vga);
+
+ memory_region_init(&d->mmio, "nv2a-mmio", 0x1000000);
+
+ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+
+ memory_region_init_ram(&d->vram, "nv2a-vram", 128 * 0x100000);
+ pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, &d->vram);
+
+ for (i=0; iblock_mmio[i], &blocktable[i].ops, d,
+ blocktable[i].name, blocktable[i].size);
+ memory_region_add_subregion(&d->mmio, blocktable[i].offset,
+ &d->block_mmio[i]);
+ }
+
+
+ return 0;
+}
+
+static void nv2a_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = PCI_VENDOR_ID_NVIDIA;
+ k->device_id = PCI_DEVICE_ID_NVIDIA_GEFORCE_NV2A;
+ k->revision = 161;
+ k->class_id = PCI_CLASS_DISPLAY_3D;
+ k->init = nv2a_initfn;
+
+ dc->desc = "GeForce NV2A Integrated Graphics";
+}
+
+static const TypeInfo nv2a_info = {
+ .name = "nv2a",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(NV2AState),
+ .class_init = nv2a_class_init,
+};
+
+static void nv2a_register(void)
+{
+ type_register_static(&nv2a_info);
+}
+type_init(nv2a_register);
+
+
+
+
+
+void nv2a_init(PCIBus *bus, int devfn)
+{
+ pci_create_simple(bus, devfn, "nv2a");
+}
\ No newline at end of file
diff --git a/hw/nv2a.h b/hw/nv2a.h
new file mode 100644
index 0000000000..8438e9adc9
--- /dev/null
+++ b/hw/nv2a.h
@@ -0,0 +1,27 @@
+/*
+ * QEMU Geforce NV2A implementation
+ *
+ * Copyright (c) 2012 espes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_NV2A_H
+#define HW_NV2A_H
+
+void nv2a_init(PCIBus *bus, int devfn);
+
+#endif
\ No newline at end of file
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 301bf1cd86..fdff5541f0 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -22,6 +22,7 @@
#define PCI_CLASS_NETWORK_ETHERNET 0x0200
#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_3D 0x0302
#define PCI_CLASS_DISPLAY_OTHER 0x0380
#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
@@ -31,6 +32,7 @@
#define PCI_CLASS_SYSTEM_OTHER 0x0880
#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_SMBUS 0x0c05
#define PCI_CLASS_BRIDGE_HOST 0x0600
#define PCI_CLASS_BRIDGE_ISA 0x0601
@@ -128,3 +130,12 @@
#define PCI_VENDOR_ID_NEC 0x1033
#define PCI_DEVICE_ID_NEC_UPD720200 0x0194
+
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_LPC 0x01b2
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_AGP 0x01b7
+
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_NV2A 0x02a0
+#define PCI_DEVICE_ID_NVIDIA_XBOX_PCHB 0x02a5
+
diff --git a/hw/smbus.h b/hw/smbus.h
index 6ed45bd03d..9dafd32d9a 100644
--- a/hw/smbus.h
+++ b/hw/smbus.h
@@ -77,7 +77,14 @@ int smbus_read_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data)
void smbus_write_block(i2c_bus *bus, uint8_t addr, uint8_t command, uint8_t *data,
int len);
+void smbus_eeprom_init_single(i2c_bus *smbus, int address,
+ uint8_t *eeprom_buf);
void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int size);
+
+void smbus_pic16lc_init(i2c_bus *smbus, int address);
+void smbus_cx25871_init(i2c_bus *smbus, int address);
+void smbus_adm1032_init(i2c_bus *smbus, int address);
+
#endif
diff --git a/hw/smbus_adm1032.c b/hw/smbus_adm1032.c
new file mode 100644
index 0000000000..178f762664
--- /dev/null
+++ b/hw/smbus_adm1032.c
@@ -0,0 +1,86 @@
+/*
+ * QEMU SMBus ADM1032 Temperature Monitor
+ *
+ * Copyright (c) 2012 espes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "i2c.h"
+#include "smbus.h"
+
+#define DEBUG
+
+static uint8_t tm_read_data(SMBusDevice *dev, uint8_t cmd, int n)
+{
+ #ifdef DEBUG
+ printf("tm_read_data: addr=0x%02x cmd=0x%02x n=%d\n",
+ dev->i2c.address, cmd, n);
+ #endif
+
+ switch (cmd) {
+ case 0x0:
+ case 0x1:
+ return 50;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int tm_init(SMBusDevice *dev)
+{
+ return 0;
+}
+
+
+static void smbus_adm1032_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass);
+
+ sc->init = tm_init;
+ sc->read_data = tm_read_data;
+}
+
+static TypeInfo smbus_adm1032_info = {
+ .name = "smbus-adm1032",
+ .parent = TYPE_SMBUS_DEVICE,
+ .instance_size = sizeof(SMBusDevice),
+ .class_init = smbus_adm1032_class_initfn,
+};
+
+
+static void smbus_adm1032_register_devices(void)
+{
+ type_register_static(&smbus_adm1032_info);
+}
+
+type_init(smbus_adm1032_register_devices)
+
+
+void smbus_adm1032_init(i2c_bus *smbus, int address)
+{
+ DeviceState *tm;
+ tm = qdev_create((BusState *)smbus, "smbus-adm1032");
+ qdev_prop_set_uint8(tm, "address", address);
+ qdev_init_nofail(tm);
+}
diff --git a/hw/smbus_cx25871.c b/hw/smbus_cx25871.c
new file mode 100644
index 0000000000..385dd3d860
--- /dev/null
+++ b/hw/smbus_cx25871.c
@@ -0,0 +1,127 @@
+/*
+ * QEMU SMBus Conexant CX25871 Video Encoder
+ *
+ * Copyright (c) 2012 espes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "i2c.h"
+#include "smbus.h"
+
+typedef struct SMBusCX25871Device {
+ SMBusDevice smbusdev;
+
+ uint8_t registers[256];
+} SMBusCX25871Device;
+
+#define DEBUG
+
+static void cx_quick_cmd(SMBusDevice *dev, uint8_t read)
+{
+#ifdef DEBUG
+ printf("cx_quick_cmd: addr=0x%02x read=%d\n", dev->i2c.address, read);
+#endif
+}
+
+static void cx_send_byte(SMBusDevice *dev, uint8_t val)
+{
+ SMBusCX25871Device *cx = (SMBusCX25871Device *) dev;
+#ifdef DEBUG
+ printf("cx_send_byte: addr=0x%02x val=0x%02x\n",
+ dev->i2c.address, val);
+#endif
+}
+
+static uint8_t cx_receive_byte(SMBusDevice *dev)
+{
+ SMBusCX25871Device *cx = (SMBusCX25871Device *) dev;
+#ifdef DEBUG
+ printf("cx_receive_byte: addr=0x%02x\n",
+ dev->i2c.address);
+#endif
+ return 0;
+}
+
+static void cx_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len)
+{
+ SMBusCX25871Device *cx = (SMBusCX25871Device *) dev;
+#ifdef DEBUG
+ printf("cx_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
+ dev->i2c.address, cmd, buf[0]);
+#endif
+
+ memcpy(cx->registers+cmd, buf, MIN(len, 256-cmd));
+}
+
+static uint8_t cx_read_data(SMBusDevice *dev, uint8_t cmd, int n)
+{
+ SMBusCX25871Device *cx = (SMBusCX25871Device *) dev;
+ #ifdef DEBUG
+ printf("cx_read_data: addr=0x%02x cmd=0x%02x n=%d\n",
+ dev->i2c.address, cmd, n);
+ #endif
+
+ return cx->registers[cmd];
+}
+
+static int smbus_cx_init(SMBusDevice *dev)
+{
+ SMBusCX25871Device *cx = (SMBusCX25871Device *)dev;
+
+ return 0;
+}
+
+static void smbus_cx25871_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass);
+
+ sc->init = smbus_cx_init;
+ sc->quick_cmd = cx_quick_cmd;
+ sc->send_byte = cx_send_byte;
+ sc->receive_byte = cx_receive_byte;
+ sc->write_data = cx_write_data;
+ sc->read_data = cx_read_data;
+}
+
+static TypeInfo smbus_cx25871_info = {
+ .name = "smbus-cx25871",
+ .parent = TYPE_SMBUS_DEVICE,
+ .instance_size = sizeof(SMBusCX25871Device),
+ .class_init = smbus_cx25871_class_initfn,
+};
+
+
+static void smbus_cx25871_register_devices(void)
+{
+ type_register_static(&smbus_cx25871_info);
+}
+
+type_init(smbus_cx25871_register_devices)
+
+
+void smbus_cx25871_init(i2c_bus *smbus, int address)
+{
+ DeviceState *cx;
+ cx = qdev_create((BusState *)smbus, "smbus-cx25871");
+ qdev_prop_set_uint8(cx, "address", address);
+ qdev_init_nofail(cx);
+}
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 11adab01b8..26d4d0ad8a 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -26,7 +26,7 @@
#include "i2c.h"
#include "smbus.h"
-//#define DEBUG
+#define DEBUG
typedef struct SMBusEEPROMDevice {
SMBusDevice smbusdev;
@@ -137,6 +137,16 @@ static void smbus_eeprom_register_types(void)
type_init(smbus_eeprom_register_types)
+void smbus_eeprom_init_single(i2c_bus *smbus, int address,
+ uint8_t *eeprom_buf)
+{
+ DeviceState *eeprom;
+ eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
+ qdev_prop_set_uint8(eeprom, "address", address);
+ qdev_prop_set_ptr(eeprom, "data", eeprom_buf);
+ qdev_init_nofail(eeprom);
+}
+
void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int eeprom_spd_size)
{
@@ -147,10 +157,7 @@ void smbus_eeprom_init(i2c_bus *smbus, int nb_eeprom,
}
for (i = 0; i < nb_eeprom; i++) {
- DeviceState *eeprom;
- eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
- qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
- qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
- qdev_init_nofail(eeprom);
+ smbus_eeprom_init_single(smbus,
+ 0x50 + i, eeprom_buf + (i * 256));
}
}
diff --git a/hw/smbus_pic16lc.c b/hw/smbus_pic16lc.c
new file mode 100644
index 0000000000..e83021a59c
--- /dev/null
+++ b/hw/smbus_pic16lc.c
@@ -0,0 +1,183 @@
+/*
+ * QEMU SMBus PIC16LC System Monitor
+ *
+ * Copyright (c) 2011 espes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "i2c.h"
+#include "smbus.h"
+
+
+#define PIC16LC_REG_VER 0x01
+#define PIC16LC_REG_POWER 0x02
+#define PIC16LC_REG_POWER_RESET 0x01
+#define PIC16LC_REG_POWER_CYCLE 0x40
+#define PIC16LC_REG_POWER_SHUTDOWN 0x80
+#define PIC16LC_REG_TRAYSTATE 0x03
+#define PIC16LC_REG_AVPACK 0x04
+#define PIC16LC_REG_AVPACK_SCART 0x00
+#define PIC16LC_REG_AVPACK_HDTV 0x01
+#define PIC16LC_REG_AVPACK_VGA_SOG 0x02
+#define PIC16LC_REG_AVPACK_SVIDEO 0x04
+#define PIC16LC_REG_AVPACK_COMPOSITE 0x06
+#define PIC16LC_REG_AVPACK_VGA 0x07
+#define PIC16LC_REG_FANMODE 0x05
+#define PIC16LC_REG_FANSPEED 0x06
+#define PIC16LC_REG_LEDMODE 0x07
+#define PIC16LC_REG_LEDSEQ 0x08
+#define PIC16LC_REG_CPUTEMP 0x09
+#define PIC16LC_REG_BOARDTEMP 0x0a
+#define PIC16LC_REG_TRAYEJECT 0x0c
+#define PIC16LC_REG_INTACK 0x0d
+#define PIC16LC_REG_INTSTATUS 0x11
+#define PIC16LC_REG_INTSTATUS_POWER 0x01
+#define PIC16LC_REG_INTSTATUS_TRAYCLOSED 0x02
+#define PIC16LC_REG_INTSTATUS_TRAYOPENING 0x04
+#define PIC16LC_REG_INTSTATUS_AVPACK_PLUG 0x08
+#define PIC16LC_REG_INTSTATUS_AVPACK_UNPLUG 0x10
+#define PIC16LC_REG_INTSTATUS_EJECT_BUTTON 0x20
+#define PIC16LC_REG_INTSTATUS_TRAYCLOSING 0x40
+#define PIC16LC_REG_RESETONEJECT 0x19
+#define PIC16LC_REG_INTEN 0x1a
+
+static const char* pic_version_string = "P01";
+
+
+#define DEBUG
+
+typedef struct SMBusPIC16LCDevice {
+ SMBusDevice smbusdev;
+ int versionStringIndex;
+} SMBusPIC16LCDevice;
+
+static void pic_quick_cmd(SMBusDevice *dev, uint8_t read)
+{
+#ifdef DEBUG
+ printf("pic_quick_cmd: addr=0x%02x read=%d\n", dev->i2c.address, read);
+#endif
+}
+
+static void pic_send_byte(SMBusDevice *dev, uint8_t val)
+{
+ SMBusPIC16LCDevice *pic = (SMBusPIC16LCDevice *) dev;
+#ifdef DEBUG
+ printf("pic_send_byte: addr=0x%02x val=0x%02x\n",
+ dev->i2c.address, val);
+#endif
+}
+
+static uint8_t pic_receive_byte(SMBusDevice *dev)
+{
+ SMBusPIC16LCDevice *pic = (SMBusPIC16LCDevice *) dev;
+#ifdef DEBUG
+ printf("pic_receive_byte: addr=0x%02x\n",
+ dev->i2c.address);
+#endif
+ return 0;
+}
+
+static void pic_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len)
+{
+ SMBusPIC16LCDevice *pic = (SMBusPIC16LCDevice *) dev;
+#ifdef DEBUG
+ printf("pic_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n",
+ dev->i2c.address, cmd, buf[0]);
+#endif
+
+ switch(cmd) {
+ case PIC16LC_REG_VER:
+ //pic version string reset
+ pic->versionStringIndex = buf[0];
+ break;
+ default:
+ break;
+ }
+}
+
+static uint8_t pic_read_data(SMBusDevice *dev, uint8_t cmd, int n)
+{
+ SMBusPIC16LCDevice *pic = (SMBusPIC16LCDevice *) dev;
+ #ifdef DEBUG
+ printf("pic_read_data: addr=0x%02x cmd=0x%02x n=%d\n",
+ dev->i2c.address, cmd, n);
+ #endif
+
+ switch(cmd) {
+ case PIC16LC_REG_VER:
+ return pic_version_string[
+ pic->versionStringIndex++%(sizeof(pic_version_string)-1)];
+ case PIC16LC_REG_AVPACK:
+ //pretend to ave a composite av pack plugged in
+ return PIC16LC_REG_AVPACK_COMPOSITE;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int smbus_pic_init(SMBusDevice *dev)
+{
+ SMBusPIC16LCDevice *pic = (SMBusPIC16LCDevice *)dev;
+
+ pic->versionStringIndex = 0;
+ return 0;
+}
+
+
+static void smbus_pic_class_initfn(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass);
+
+ sc->init = smbus_pic_init;
+ sc->quick_cmd = pic_quick_cmd;
+ sc->send_byte = pic_send_byte;
+ sc->receive_byte = pic_receive_byte;
+ sc->write_data = pic_write_data;
+ sc->read_data = pic_read_data;
+}
+
+static TypeInfo smbus_pic_info = {
+ .name = "smbus-pic16lc",
+ .parent = TYPE_SMBUS_DEVICE,
+ .instance_size = sizeof(SMBusPIC16LCDevice),
+ .class_init = smbus_pic_class_initfn,
+};
+
+
+
+static void smbus_pic_register_devices(void)
+{
+ type_register_static(&smbus_pic_info);
+}
+
+type_init(smbus_pic_register_devices)
+
+
+void smbus_pic16lc_init(i2c_bus *smbus, int address)
+{
+ DeviceState *pic;
+ pic = qdev_create((BusState *)smbus, "smbus-pic16lc");
+ qdev_prop_set_uint8(pic, "address", address);
+ qdev_init_nofail(pic);
+}
diff --git a/hw/xbox.c b/hw/xbox.c
new file mode 100644
index 0000000000..5bc134cd20
--- /dev/null
+++ b/hw/xbox.c
@@ -0,0 +1,276 @@
+/*
+ * QEMU Xbox System Emulator
+ *
+ * Copyright (c) 2012 espes
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "arch_init.h"
+#include "pc.h"
+#include "pci.h"
+#include "net.h"
+#include "boards.h"
+#include "ide.h"
+#include "mc146818rtc.h"
+#include "i8254.h"
+#include "pcspk.h"
+#include "kvm.h"
+#include "sysemu.h"
+#include "sysbus.h"
+#include "smbus.h"
+#include "blockdev.h"
+#include "loader.h"
+#include "exec-memory.h"
+
+#include "xbox_pci.h"
+#include "nv2a.h"
+
+
+/* mostly from pc_memory_init */
+static void xbox_memory_init(MemoryRegion *system_memory,
+ ram_addr_t mem_size,
+ MemoryRegion *rom_memory,
+ MemoryRegion **ram_memory)
+{
+ MemoryRegion *ram;
+ MemoryRegion *ram_below_4g;
+
+ int ret;
+ char *filename;
+ int bios_size, isa_bios_size;
+ MemoryRegion *bios, *isa_bios;
+
+ MemoryRegion *map_bios;
+ uint32_t map_loc;
+
+ /* Allocate RAM. We allocate it as a single memory region and use
+ * aliases to address portions of it, mostly for backwards compatibility
+ * with older qemus that used qemu_ram_alloc().
+ */
+ ram = g_malloc(sizeof(*ram));
+ memory_region_init_ram(ram, "pc.ram", mem_size);
+ vmstate_register_ram_global(ram);
+ *ram_memory = ram;
+ ram_below_4g = g_malloc(sizeof(*ram_below_4g));
+ memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+ 0, mem_size);
+ memory_region_add_subregion(system_memory, 0, ram_below_4g);
+
+
+ /* Load the bios. (mostly from pc_sysfw)
+ * Can't use it verbatim, since we need the bios repeated\
+ * over top 1MB of memory.
+ */
+ if (bios_name == NULL) {
+ bios_name = "bios.bin";
+ }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (filename) {
+ bios_size = get_image_size(filename);
+ } else {
+ bios_size = -1;
+ }
+ bios = g_malloc(sizeof(*bios));
+ memory_region_init_ram(bios, "pc.bios", bios_size);
+ vmstate_register_ram_global(bios);
+ memory_region_set_readonly(bios, true);
+ ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
+ if (ret != 0) {
+ fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
+ exit(1);
+ }
+ if (filename) {
+ g_free(filename);
+ }
+
+
+
+ /* map the last 128KB of the BIOS in ISA space */
+ isa_bios_size = bios_size;
+ if (isa_bios_size > (128 * 1024)) {
+ isa_bios_size = 128 * 1024;
+ }
+ isa_bios = g_malloc(sizeof(*isa_bios));
+ memory_region_init_alias(isa_bios, "isa-bios", bios,
+ bios_size - isa_bios_size, isa_bios_size);
+ memory_region_add_subregion_overlap(rom_memory,
+ 0x100000 - isa_bios_size,
+ isa_bios,
+ 1);
+ memory_region_set_readonly(isa_bios, true);
+
+
+ /* map the bios repeated at the top of memory */
+ for (map_loc=(uint32_t)(-bios_size); map_loc >= 0xff000000; map_loc-=bios_size) {
+ map_bios = g_malloc(sizeof(*map_bios));
+ memory_region_init_alias(map_bios, NULL, bios, 0, bios_size);
+
+ memory_region_add_subregion(rom_memory, map_loc, map_bios);
+ memory_region_set_readonly(map_bios, true);
+ }
+
+ /*memory_region_add_subregion(rom_memory,
+ (uint32_t)(-bios_size),
+ bios);
+ */
+
+}
+
+
+
+static void ioapic_init(GSIState *gsi_state)
+{
+ DeviceState *dev;
+ SysBusDevice *d;
+ unsigned int i;
+
+ dev = qdev_create(NULL, "ioapic");
+
+ qdev_init_nofail(dev);
+ d = sysbus_from_qdev(dev);
+ sysbus_mmio_map(d, 0, 0xfec00000);
+
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
+ }
+}
+
+
+#define MAX_IDE_BUS 2
+
+/* mostly from pc_init1 */
+static void xbox_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ int i;
+ PCIBus *host_bus;
+ ISABus *isa_bus;
+ qemu_irq *cpu_irq;
+ qemu_irq *gsi;
+ qemu_irq *i8259;
+ GSIState *gsi_state;
+ PCIDevice *ide_dev;
+ DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ BusState *idebus[MAX_IDE_BUS];
+ ISADevice *rtc_state;
+ ISADevice *pit;
+ MemoryRegion *ram_memory;
+ MemoryRegion *pci_memory;
+
+ DeviceState *xboxpci_host;
+ i2c_bus *smbus;
+ PCIBus *agp_bus;
+
+
+ pc_cpus_init(cpu_model);
+
+ pci_memory = g_new(MemoryRegion, 1);
+ memory_region_init(pci_memory, "pci", INT64_MAX);
+
+ /* allocate ram and load rom/bios */
+ xbox_memory_init(get_system_memory(), ram_size,
+ pci_memory, &ram_memory);
+
+
+ gsi_state = g_malloc0(sizeof(*gsi_state));
+ gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+
+
+ /* init buses */
+ host_bus = xbox_pci_init(&xboxpci_host, gsi,
+ get_system_memory(), get_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);
+
+
+ /* irq shit */
+ isa_bus_irqs(isa_bus, gsi);
+ cpu_irq = pc_allocate_cpu_irq();
+ i8259 = i8259_init(isa_bus, cpu_irq[0]);
+
+ for (i = 0; i < ISA_NUM_IRQS; i++) {
+ gsi_state->i8259_irq[i] = i8259[i];
+ }
+ ioapic_init(gsi_state);
+
+
+ /* basic device init */
+ rtc_state = rtc_init(isa_bus, 2000, NULL);
+ pit = pit_init(isa_bus, 0x40, 0, NULL);
+
+ /* does apparently have a pc speaker, though not used? */
+ pcspk_init(isa_bus, pit);
+
+
+ /* TODO: ethernet */
+
+ /* TODO: USB */
+
+ /* hdd shit
+ * piix3's ide be right for now, maybe
+ */
+
+
+ ide_drive_get(hd, MAX_IDE_BUS);
+ ide_dev = pci_piix4_ide_init(host_bus, hd, PCI_DEVFN(9, 0));
+
+ idebus[0] = qdev_get_child_bus(&ide_dev->qdev, "ide.0");
+ idebus[1] = qdev_get_child_bus(&ide_dev->qdev, "ide.1");
+
+
+ pc_cmos_init(ram_size, 0, boot_device,
+ NULL, idebus[0], idebus[1], rtc_state);
+
+
+ /* TODO: Populate SPD eeprom data. */
+ uint8_t *eeprom_buf = g_malloc0(256);
+ smbus_eeprom_init_single(smbus, 0x54, eeprom_buf);
+
+ smbus_pic16lc_init(smbus, 0x10);
+ smbus_cx25871_init(smbus, 0x45);
+ smbus_adm1032_init(smbus, 0x4c);
+
+
+
+ /* GPU! */
+ nv2a_init(agp_bus, PCI_DEVFN(0, 0));
+}
+
+static QEMUMachine xbox_machine = {
+ .name = "xbox",
+ .desc = "Microsoft Xbox",
+ .init = xbox_init,
+};
+
+static void xbox_machine_init(void) {
+ qemu_register_machine(&xbox_machine);
+}
+
+machine_init(xbox_machine_init);
\ No newline at end of file
diff --git a/hw/xbox_pci.c b/hw/xbox_pci.c
new file mode 100644
index 0000000000..b46a970e37
--- /dev/null
+++ b/hw/xbox_pci.c
@@ -0,0 +1,404 @@
+/*
+ * QEMU Xbox PCI buses implementation
+ *
+ * Copyright (c) 2012 espes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw.h"
+#include "range.h"
+#include "isa.h"
+#include "sysbus.h"
+#include "pc.h"
+#include "pci.h"
+#include "pci_bridge.h"
+#include "pci_internals.h"
+#include "exec-memory.h"
+#include "acpi_mcpx.h"
+#include "amd_smbus.h"
+#include "qemu-common.h"
+
+#include "xbox_pci.h"
+
+
+ /*
+ * xbox chipset based on nForce 420, which was based on AMD-760
+ *
+ * http://support.amd.com/us/ChipsetMotherboard_TechDocs/24494.pdf
+ * http://support.amd.com/us/ChipsetMotherboard_TechDocs/24416.pdf
+ * http://support.amd.com/us/ChipsetMotherboard_TechDocs/24467.pdf
+ *
+ * http://support.amd.com/us/ChipsetMotherboard_TechDocs/24462.pdf
+ *
+ * - 'NV2A' combination northbridge/gpu
+ * - 'MCPX' combination southbridge/apu
+ */
+
+
+#define DEBUG
+
+#ifdef DEBUG
+# define XBOXPCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define XBOXPCI_DPRINTF(format, ...) do { } while (0)
+#endif
+
+
+
+
+
+PCIBus *xbox_pci_init(DeviceState **xbox_pci_hostp,
+ qemu_irq *pic,
+ MemoryRegion *address_space_mem,
+ MemoryRegion *address_space_io,
+ MemoryRegion *pci_memory,
+ MemoryRegion *ram_memory)
+
+{
+ DeviceState *dev;
+ PCIHostState *hostState;
+ PCIBus *hostBus;
+ PCIDevice *bridgeDev;
+ XBOX_PCIState *bridge;
+
+ /* pci host bus */
+ dev = qdev_create(NULL, "xbox-pcihost");
+ hostState = PCI_HOST_BRIDGE(dev);
+ hostState->address_space = address_space_mem;
+
+
+ hostBus = pci_bus_new(dev, NULL, pci_memory,
+ address_space_io, 0);
+ hostState->bus = hostBus;
+
+ //pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
+ // PIIX_NUM_PIRQS);
+
+ qdev_init_nofail(dev);
+
+ bridgeDev = pci_create_simple_multifunction(hostBus, PCI_DEVFN(0, 0),
+ true, "xbox-pci");
+ bridge = XBOX_PCI_DEVICE(bridgeDev);
+ bridge->ram_memory = ram_memory;
+ bridge->pci_address_space = pci_memory;
+ bridge->system_memory = address_space_mem;
+
+ /* PCI hole */
+ memory_region_init_alias(&bridge->pci_hole, "pci-hole",
+ bridge->pci_address_space,
+ ram_size,
+ 0x100000000ULL - ram_size);
+ memory_region_add_subregion(bridge->system_memory, ram_size,
+ &bridge->pci_hole);
+
+
+ *xbox_pci_hostp = dev;
+ return hostBus;
+}
+
+
+PCIBus *xbox_agp_init(DeviceState *host, 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 = DO_UPCAST(PCIBridge, dev, d);
+ //qdev = &br->dev.qdev;
+ //qdev_init_nofail(qdev);
+
+ return pci_bridge_get_sec_bus(br);
+}
+
+
+ISABus *mcpx_lpc_init(DeviceState *host, PCIBus *bus)
+{
+ PCIDevice *d;
+ MCPX_LPCState *s;
+ //qemu_irq *sci_irq;
+
+ d = pci_create_simple_multifunction(bus, PCI_DEVFN(1, 0),
+ true, "mcpx-lpc");
+
+ 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_lpc_reset(&s->dev.qdev);
+
+ return s->isa_bus;
+}
+
+
+i2c_bus *mcpx_smbus_init(DeviceState *host, PCIBus *bus)
+{
+ PCIDevice *d;
+ MCPX_SMBState *s;
+
+ d = pci_create_simple_multifunction(bus, PCI_DEVFN(1, 1),
+ true, "mcpx-smbus");
+
+ s = MCPX_SMBUS_DEVICE(d);
+
+ return s->smb.smbus;
+}
+
+
+
+
+
+static int mcpx_smbus_initfn(PCIDevice *dev)
+{
+ MCPX_SMBState *s = MCPX_SMBUS_DEVICE(dev);
+
+ //presumably configurable, but can't find docs...
+ const uint32_t smb_io_base = 0xc000;
+ register_ioport_write(smb_io_base, 64, 1, amd756_smb_ioport_writeb, &s->smb);
+ register_ioport_read(smb_io_base, 64, 1, amd756_smb_ioport_readb, &s->smb);
+
+ amd756_smbus_init(&dev->qdev, &s->smb);
+
+ return 0;
+}
+
+
+static void mcpx_smbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = mcpx_smbus_initfn;
+ k->vendor_id = PCI_VENDOR_ID_NVIDIA;
+ k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS;
+ k->revision = 161;
+ k->class_id = PCI_CLASS_SERIAL_SMBUS;
+
+ dc->desc = "nForce PCI System Management";
+ dc->no_user = 1;
+}
+
+static const TypeInfo mcpx_smbus_info = {
+ .name = "mcpx-smbus",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = mcpx_smbus_class_init,
+};
+
+
+
+
+#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)
+{
+ MCPX_LPCState *lpc = MCPX_LPC_DEVICE(d);
+ ISABus *isa_bus;
+
+ isa_bus = isa_bus_new(&d->qdev, get_system_io());
+ lpc->isa_bus = isa_bus;
+
+ return 0;
+}
+
+static void mcpx_lpc_pmbase_update(MCPX_LPCState *s)
+{
+ uint32_t pm_io_base = pci_get_long(s->dev.config + MCPX_LPC_PMBASE);
+ pm_io_base &= MCPX_LPC_PMBASE_ADDRESS_MASK;
+
+ mcpx_pm_iospace_update(&s->pm, pm_io_base);
+}
+
+static void mcpx_lpc_reset(DeviceState *dev)
+{
+ PCIDevice *d = PCI_DEVICE(dev);
+ MCPX_LPCState *s = MCPX_LPC_DEVICE(d);
+
+ pci_set_long(s->dev.config + MCPX_LPC_PMBASE, MCPX_LPC_PMBASE_DEFAULT);
+ mcpx_lpc_pmbase_update(s);
+}
+
+static void mcpx_lpc_config_write(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len)
+{
+ MCPX_LPCState *s = MCPX_LPC_DEVICE(dev);
+
+ pci_default_write_config(dev, addr, val, len);
+ if (ranges_overlap(addr, len, MCPX_LPC_PMBASE, 2)) {
+ mcpx_lpc_pmbase_update(s);
+ }
+}
+
+static int mcpx_lpc_post_load(void *opaque, int version_id)
+{
+ MCPX_LPCState *s = opaque;
+ mcpx_lpc_pmbase_update(s);
+ return 0;
+}
+
+static const VMStateDescription vmstate_mcpx_lpc = {
+ .name = "MCPX LPC",
+ .version_id = 1,
+ .post_load = mcpx_lpc_post_load,
+};
+
+static void mcpx_lpc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = mcpx_lpc_initfn;
+ 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;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+
+ dc->desc = "nForce LPC Bridge";
+ dc->no_user = 1;
+ dc->reset = mcpx_lpc_reset;
+ dc->vmsd = &vmstate_mcpx_lpc;
+}
+
+static const TypeInfo mcpx_lpc_info = {
+ .name = "mcpx-lpc",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = mcpx_lpc_class_init,
+};
+
+
+
+
+static void xbox_agp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = pci_bridge_initfn;
+ k->exit = pci_bridge_exitfn;
+ k->config_write = pci_bridge_write_config;
+ k->is_bridge = 1;
+ k->vendor_id = PCI_VENDOR_ID_NVIDIA;
+ k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_AGP;
+ k->revision = 161;
+
+ dc->desc = "nForce AGP to PCI Bridge";
+ dc->reset = pci_bridge_reset;
+}
+
+static const TypeInfo xbox_agp_info = {
+ .name = "xbox-agp",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIBridge),
+ .class_init = xbox_agp_class_init,
+};
+
+
+
+
+
+
+static int xbox_pci_initfn(PCIDevice *d)
+{
+ //XBOX_PCIState *s = DO_UPCAST(XBOX_PCIState, dev, dev);
+
+ return 0;
+}
+
+static void xbox_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->no_hotplug = 1;
+ k->init = xbox_pci_initfn;
+ //k->config_write = xbox_pci_write_config;
+ k->vendor_id = PCI_VENDOR_ID_NVIDIA;
+ k->device_id = PCI_DEVICE_ID_NVIDIA_XBOX_PCHB;
+ k->revision = 161;
+ k->class_id = PCI_CLASS_BRIDGE_HOST;
+
+ dc->desc = "Xbox PCI Host";
+ dc->no_user = 1;
+}
+
+static const TypeInfo xbox_pci_info = {
+ .name = "xbox-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XBOX_PCIState),
+ .class_init = xbox_pci_class_init,
+};
+
+
+
+#define CONFIG_ADDR 0xcf8
+#define CONFIG_DATA 0xcfc
+
+static int xbox_pcihost_initfn(SysBusDevice *dev)
+{
+ PCIHostState *s = PCI_HOST_BRIDGE(dev);
+
+ memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s,
+ "pci-conf-idx", 4);
+ sysbus_add_io(dev, CONFIG_ADDR, &s->conf_mem);
+ sysbus_init_ioports(&s->busdev, CONFIG_ADDR, 4);
+
+ memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
+ "pci-conf-data", 4);
+ sysbus_add_io(dev, CONFIG_DATA, &s->data_mem);
+ sysbus_init_ioports(&s->busdev, CONFIG_DATA, 4);
+
+ return 0;
+}
+
+
+static void xbox_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = xbox_pcihost_initfn;
+ dc->no_user = 1;
+}
+
+static const TypeInfo xbox_pcihost_info = {
+ .name = "xbox-pcihost",
+ .parent = TYPE_PCI_HOST_BRIDGE,
+ .instance_size = sizeof(PCIHostState),
+ .class_init = xbox_pcihost_class_init,
+};
+
+
+static void xboxpci_register_types(void)
+{
+ type_register(&xbox_pcihost_info);
+ type_register(&xbox_pci_info);
+ type_register(&xbox_agp_info);
+
+ type_register(&mcpx_lpc_info);
+ type_register(&mcpx_smbus_info);
+}
+
+type_init(xboxpci_register_types)
diff --git a/hw/xbox_pci.h b/hw/xbox_pci.h
new file mode 100644
index 0000000000..3e805ef56a
--- /dev/null
+++ b/hw/xbox_pci.h
@@ -0,0 +1,81 @@
+/*
+ * QEMU Xbox PCI buses implementation
+ *
+ * Copyright (c) 2012 espes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef HW_XBOX_PCI_H
+#define HW_XBOX_PCI_H
+
+#include "hw.h"
+#include "isa.h"
+#include "pci.h"
+#include "pci_host.h"
+#include "amd_smbus.h"
+#include "acpi.h"
+#include "acpi_mcpx.h"
+
+
+typedef struct XBOX_PCIState {
+ PCIDevice dev;
+
+ MemoryRegion *ram_memory;
+ MemoryRegion *pci_address_space;
+ MemoryRegion *system_memory;
+ MemoryRegion pci_hole;
+} XBOX_PCIState;
+
+typedef struct MCPX_SMBState {
+ PCIDevice dev;
+
+ AMD756SMBus smb;
+} MCPX_SMBState;
+
+typedef struct MCPX_LPCState {
+ PCIDevice dev;
+
+ ISABus *isa_bus;
+ MCPX_PMRegs pm;
+} MCPX_LPCState;
+
+#define XBOX_PCI_DEVICE(obj) \
+ OBJECT_CHECK(XBOX_PCIState, (obj), "xbox-pci")
+
+#define MCPX_SMBUS_DEVICE(obj) \
+ OBJECT_CHECK(MCPX_SMBState, (obj), "mcpx-smbus")
+
+#define MCPX_LPC_DEVICE(obj) \
+ OBJECT_CHECK(MCPX_LPCState, (obj), "mcpx-lpc")
+
+
+
+PCIBus *xbox_pci_init(DeviceState **xbox_pci_hostp,
+ 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);
+
+ISABus *mcpx_lpc_init(DeviceState *host, PCIBus *bus);
+
+i2c_bus *mcpx_smbus_init(DeviceState *host, PCIBus *bus);
+
+
+#endif
\ No newline at end of file