]> git.proxmox.com Git - qemu.git/commitdiff
hw: move PCI bridges to hw/pci-* or hw/ARCH
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 5 Feb 2013 14:06:20 +0000 (15:06 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 8 Apr 2013 16:13:14 +0000 (18:13 +0200)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
58 files changed:
default-configs/i386-softmmu.mak
default-configs/sparc64-softmmu.mak
default-configs/x86_64-softmmu.mak
hw/Makefile.objs
hw/alpha/Makefile.objs
hw/alpha/typhoon.c [new file with mode: 0644]
hw/alpha_typhoon.c [deleted file]
hw/apb_pci.c [deleted file]
hw/bonito.c [deleted file]
hw/gt64xxx.c [deleted file]
hw/i386/Makefile.objs
hw/mips/Makefile.objs
hw/mips/gt64xxx_pci.c [new file with mode: 0644]
hw/pci-bridge/Makefile.objs [new file with mode: 0644]
hw/pci-bridge/i82801b11.c [new file with mode: 0644]
hw/pci-bridge/ioh3420.c [new file with mode: 0644]
hw/pci-bridge/pci_bridge_dev.c [new file with mode: 0644]
hw/pci-bridge/xio3130_downstream.c [new file with mode: 0644]
hw/pci-bridge/xio3130_upstream.c [new file with mode: 0644]
hw/pci-host/Makefile.objs [new file with mode: 0644]
hw/pci-host/apb.c [new file with mode: 0644]
hw/pci-host/bonito.c [new file with mode: 0644]
hw/pci-host/dec.c [new file with mode: 0644]
hw/pci-host/grackle.c [new file with mode: 0644]
hw/pci-host/pam.c [new file with mode: 0644]
hw/pci-host/piix.c [new file with mode: 0644]
hw/pci-host/ppce500.c [new file with mode: 0644]
hw/pci-host/prep.c [new file with mode: 0644]
hw/pci-host/q35.c [new file with mode: 0644]
hw/pci-host/uninorth.c [new file with mode: 0644]
hw/pci-host/versatile.c [new file with mode: 0644]
hw/pci/Makefile.objs
hw/pci/bridge/Makefile.objs [deleted file]
hw/pci/bridge/i82801b11.c [deleted file]
hw/pci/bridge/ioh3420.c [deleted file]
hw/pci/bridge/pci_bridge_dev.c [deleted file]
hw/pci/bridge/xio3130_downstream.c [deleted file]
hw/pci/bridge/xio3130_upstream.c [deleted file]
hw/pci/host/Makefile.objs [deleted file]
hw/pci/host/dec.c [deleted file]
hw/pci/host/grackle.c [deleted file]
hw/pci/host/pam.c [deleted file]
hw/pci/host/ppce500.c [deleted file]
hw/pci/host/prep.c [deleted file]
hw/pci/host/uninorth.c [deleted file]
hw/pci/host/versatile.c [deleted file]
hw/piix_pci.c [deleted file]
hw/ppc/Makefile.objs
hw/ppc/ppc4xx_pci.c [new file with mode: 0644]
hw/ppc/spapr_pci.c [new file with mode: 0644]
hw/ppc4xx_pci.c [deleted file]
hw/q35.c [deleted file]
hw/sh4/Makefile.objs
hw/sh4/sh_pci.c [new file with mode: 0644]
hw/sh_pci.c [deleted file]
hw/spapr_pci.c [deleted file]
hw/sparc64/Makefile.objs
include/hw/pci-host/q35.h

index 717c8f452f3b2dab965e309638c9b074241791e6..fa070cd981ddead89b1a12d64f03816b16ab2b98 100644 (file)
@@ -31,8 +31,12 @@ CONFIG_TPM_TIS=y
 CONFIG_TPM_PASSTHROUGH=y
 CONFIG_PCI_HOTPLUG=y
 CONFIG_MC146818RTC=y
+CONFIG_PAM=y
+CONFIG_PCI_PIIX=y
+CONFIG_PCI_HOTPLUG=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
 CONFIG_ISA_DEBUG=y
 CONFIG_LPC_ICH9=y
+CONFIG_Q35=y
index 3b3dc55cbd907b6dfe8fb0f73364d37916bd60fb..9b08ee8a20568cb3d0483c074e669d9cbf97b9b6 100644 (file)
@@ -13,4 +13,5 @@ CONFIG_PCKBD=y
 CONFIG_FDC=y
 CONFIG_IDE_ISA=y
 CONFIG_IDE_CMD646=y
+CONFIG_PCI_APB=y
 CONFIG_MC146818RTC=y
index 31de9453a9210c17f41e5a095607df8059d4222f..3102c09066461256204e72a9ab2b3384e7ad2a70 100644 (file)
@@ -31,8 +31,12 @@ CONFIG_TPM_TIS=y
 CONFIG_TPM_PASSTHROUGH=y
 CONFIG_PCI_HOTPLUG=y
 CONFIG_MC146818RTC=y
+CONFIG_PAM=y
+CONFIG_PCI_PIIX=y
+CONFIG_PCI_HOTPLUG=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
 CONFIG_ISA_DEBUG=y
 CONFIG_LPC_ICH9=y
+CONFIG_Q35=y
index eef8742af3ddf773aae3a7057239841d58809ba6..8d0cc1fa9cfbcf8d2d2b700ac1ff77ec1778a0df 100644 (file)
@@ -17,6 +17,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += misc/
 devices-dirs-$(CONFIG_SOFTMMU) += net/
 devices-dirs-$(CONFIG_SOFTMMU) += nvram/
 devices-dirs-$(CONFIG_SOFTMMU) += pci/
+devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/
 devices-dirs-$(CONFIG_SOFTMMU) += scsi/
 devices-dirs-$(CONFIG_SOFTMMU) += sd/
 devices-dirs-$(CONFIG_SOFTMMU) += ssi/
index 5dfea7aaa1f0b98724bf1ea7e0d7ba042d56e918..5c742756f016401178e6676946a35af5ec875ab7 100644 (file)
@@ -1,5 +1 @@
-obj-y += alpha_typhoon.o
-
-obj-y := $(addprefix ../,$(obj-y))
-
-obj-y += dp264.o pci.o
+obj-y += dp264.o pci.o typhoon.o
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
new file mode 100644 (file)
index 0000000..41a0ebc
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation.
+ *
+ * Written by Richard Henderson.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ */
+
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "hw/hw.h"
+#include "hw/arm/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/alpha_sys.h"
+#include "exec/address-spaces.h"
+
+
+#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
+
+typedef struct TyphoonCchip {
+    MemoryRegion region;
+    uint64_t misc;
+    uint64_t drir;
+    uint64_t dim[4];
+    uint32_t iic[4];
+    AlphaCPU *cpu[4];
+} TyphoonCchip;
+
+typedef struct TyphoonWindow {
+    uint32_t base_addr;
+    uint32_t mask;
+    uint32_t translated_base_pfn;
+} TyphoonWindow;
+typedef struct TyphoonPchip {
+    MemoryRegion region;
+    MemoryRegion reg_iack;
+    MemoryRegion reg_mem;
+    MemoryRegion reg_io;
+    MemoryRegion reg_conf;
+    uint64_t ctl;
+    TyphoonWindow win[4];
+} TyphoonPchip;
+
+#define TYPHOON_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
+
+typedef struct TyphoonState {
+    PCIHostState parent_obj;
+
+    TyphoonCchip cchip;
+    TyphoonPchip pchip;
+    MemoryRegion dchip_region;
+    MemoryRegion ram_region;
+
+    /* QEMU emulation state.  */
+    uint32_t latch_tmp;
+} TyphoonState;
+
+/* Called when one of DRIR or DIM changes.  */
+static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
+{
+    /* If there are any non-masked interrupts, tell the cpu.  */
+    if (cpu != NULL) {
+        CPUState *cs = CPU(cpu);
+        if (req) {
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+
+static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
+{
+    CPUAlphaState *env = cpu_single_env;
+    TyphoonState *s = opaque;
+    CPUState *cpu;
+    uint64_t ret = 0;
+
+    if (addr & 4) {
+        return s->latch_tmp;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* CSC: Cchip System Configuration Register.  */
+        /* All sorts of data here; probably the only thing relevant is
+           PIP<14> Pchip 1 Present = 0.  */
+        break;
+
+    case 0x0040:
+        /* MTR: Memory Timing Register.  */
+        /* All sorts of stuff related to real DRAM.  */
+        break;
+
+    case 0x0080:
+        /* MISC: Miscellaneous Register.  */
+        cpu = ENV_GET_CPU(env);
+        ret = s->cchip.misc | (cpu->cpu_index & 3);
+        break;
+
+    case 0x00c0:
+        /* MPD: Memory Presence Detect Register.  */
+        break;
+
+    case 0x0100: /* AAR0 */
+    case 0x0140: /* AAR1 */
+    case 0x0180: /* AAR2 */
+    case 0x01c0: /* AAR3 */
+        /* AAR: Array Address Register.  */
+        /* All sorts of information about DRAM.  */
+        break;
+
+    case 0x0200:
+        /* DIM0: Device Interrupt Mask Register, CPU0.  */
+        ret = s->cchip.dim[0];
+        break;
+    case 0x0240:
+        /* DIM1: Device Interrupt Mask Register, CPU1.  */
+        ret = s->cchip.dim[1];
+        break;
+    case 0x0280:
+        /* DIR0: Device Interrupt Request Register, CPU0.  */
+        ret = s->cchip.dim[0] & s->cchip.drir;
+        break;
+    case 0x02c0:
+        /* DIR1: Device Interrupt Request Register, CPU1.  */
+        ret = s->cchip.dim[1] & s->cchip.drir;
+        break;
+    case 0x0300:
+        /* DRIR: Device Raw Interrupt Request Register.  */
+        ret = s->cchip.drir;
+        break;
+
+    case 0x0340:
+        /* PRBEN: Probe Enable Register.  */
+        break;
+
+    case 0x0380:
+        /* IIC0: Interval Ignore Count Register, CPU0.  */
+        ret = s->cchip.iic[0];
+        break;
+    case 0x03c0:
+        /* IIC1: Interval Ignore Count Register, CPU1.  */
+        ret = s->cchip.iic[1];
+        break;
+
+    case 0x0400: /* MPR0 */
+    case 0x0440: /* MPR1 */
+    case 0x0480: /* MPR2 */
+    case 0x04c0: /* MPR3 */
+        /* MPR: Memory Programming Register.  */
+        break;
+
+    case 0x0580:
+        /* TTR: TIGbus Timing Register.  */
+        /* All sorts of stuff related to interrupt delivery timings.  */
+        break;
+    case 0x05c0:
+        /* TDR: TIGbug Device Timing Register.  */
+        break;
+
+    case 0x0600:
+        /* DIM2: Device Interrupt Mask Register, CPU2.  */
+        ret = s->cchip.dim[2];
+        break;
+    case 0x0640:
+        /* DIM3: Device Interrupt Mask Register, CPU3.  */
+        ret = s->cchip.dim[3];
+        break;
+    case 0x0680:
+        /* DIR2: Device Interrupt Request Register, CPU2.  */
+        ret = s->cchip.dim[2] & s->cchip.drir;
+        break;
+    case 0x06c0:
+        /* DIR3: Device Interrupt Request Register, CPU3.  */
+        ret = s->cchip.dim[3] & s->cchip.drir;
+        break;
+
+    case 0x0700:
+        /* IIC2: Interval Ignore Count Register, CPU2.  */
+        ret = s->cchip.iic[2];
+        break;
+    case 0x0740:
+        /* IIC3: Interval Ignore Count Register, CPU3.  */
+        ret = s->cchip.iic[3];
+        break;
+
+    case 0x0780:
+        /* PWR: Power Management Control.   */
+        break;
+    
+    case 0x0c00: /* CMONCTLA */
+    case 0x0c40: /* CMONCTLB */
+    case 0x0c80: /* CMONCNT01 */
+    case 0x0cc0: /* CMONCNT23 */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
+        return -1;
+    }
+
+    s->latch_tmp = ret >> 32;
+    return ret;
+}
+
+static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
+{
+    /* Skip this.  It's all related to DRAM timing and setup.  */
+    return 0;
+}
+
+static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t ret = 0;
+
+    if (addr & 4) {
+        return s->latch_tmp;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* WSBA0: Window Space Base Address Register.  */
+        ret = s->pchip.win[0].base_addr;
+        break;
+    case 0x0040:
+        /* WSBA1 */
+        ret = s->pchip.win[1].base_addr;
+        break;
+    case 0x0080:
+        /* WSBA2 */
+        ret = s->pchip.win[2].base_addr;
+        break;
+    case 0x00c0:
+        /* WSBA3 */
+        ret = s->pchip.win[3].base_addr;
+        break;
+
+    case 0x0100:
+        /* WSM0: Window Space Mask Register.  */
+        ret = s->pchip.win[0].mask;
+        break;
+    case 0x0140:
+        /* WSM1 */
+        ret = s->pchip.win[1].mask;
+        break;
+    case 0x0180:
+        /* WSM2 */
+        ret = s->pchip.win[2].mask;
+        break;
+    case 0x01c0:
+        /* WSM3 */
+        ret = s->pchip.win[3].mask;
+        break;
+
+    case 0x0200:
+        /* TBA0: Translated Base Address Register.  */
+        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
+        break;
+    case 0x0240:
+        /* TBA1 */
+        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
+        break;
+    case 0x0280:
+        /* TBA2 */
+        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
+        break;
+    case 0x02c0:
+        /* TBA3 */
+        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
+        break;
+
+    case 0x0300:
+        /* PCTL: Pchip Control Register.  */
+        ret = s->pchip.ctl;
+        break;
+    case 0x0340:
+        /* PLAT: Pchip Master Latency Register.  */
+        break;
+    case 0x03c0:
+        /* PERROR: Pchip Error Register.  */
+        break;
+    case 0x0400:
+        /* PERRMASK: Pchip Error Mask Register.  */
+        break;
+    case 0x0440:
+        /* PERRSET: Pchip Error Set Register.  */
+        break;
+    case 0x0480:
+        /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
+        break;
+    case 0x04c0:
+        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
+        break;
+    case 0x0500: /* PMONCTL */
+    case 0x0540: /* PMONCNT */
+    case 0x0800: /* SPRST */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
+        return -1;
+    }
+
+    s->latch_tmp = ret >> 32;
+    return ret;
+}
+
+static void cchip_write(void *opaque, hwaddr addr,
+                        uint64_t v32, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t val, oldval, newval;
+
+    if (addr & 4) {
+        val = v32 << 32 | s->latch_tmp;
+        addr ^= 4;
+    } else {
+        s->latch_tmp = v32;
+        return;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* CSC: Cchip System Configuration Register.  */
+        /* All sorts of data here; nothing relevant RW.  */
+        break;
+
+    case 0x0040:
+        /* MTR: Memory Timing Register.  */
+        /* All sorts of stuff related to real DRAM.  */
+        break;
+
+    case 0x0080:
+        /* MISC: Miscellaneous Register.  */
+        newval = oldval = s->cchip.misc;
+        newval &= ~(val & 0x10000ff0);     /* W1C fields */
+        if (val & 0x100000) {
+            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
+        } else {
+            newval |= val & 0x00f00000;    /* ABT field is W1S */
+            if ((newval & 0xf0000) == 0) {
+                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
+            }
+        }
+        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
+
+        newval &= ~0xf0000000000ull;       /* WO and RW fields */
+        newval |= val & 0xf0000000000ull;
+        s->cchip.misc = newval;
+
+        /* Pass on changes to IPI and ITI state.  */
+        if ((newval ^ oldval) & 0xff0) {
+            int i;
+            for (i = 0; i < 4; ++i) {
+                AlphaCPU *cpu = s->cchip.cpu[i];
+                if (cpu != NULL) {
+                    CPUState *cs = CPU(cpu);
+                    /* IPI can be either cleared or set by the write.  */
+                    if (newval & (1 << (i + 8))) {
+                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
+                    } else {
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
+                    }
+
+                    /* ITI can only be cleared by the write.  */
+                    if ((newval & (1 << (i + 4))) == 0) {
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
+                    }
+                }
+            }
+        }
+        break;
+
+    case 0x00c0:
+        /* MPD: Memory Presence Detect Register.  */
+        break;
+
+    case 0x0100: /* AAR0 */
+    case 0x0140: /* AAR1 */
+    case 0x0180: /* AAR2 */
+    case 0x01c0: /* AAR3 */
+        /* AAR: Array Address Register.  */
+        /* All sorts of information about DRAM.  */
+        break;
+
+    case 0x0200: /* DIM0 */
+        /* DIM: Device Interrupt Mask Register, CPU0.  */
+        s->cchip.dim[0] = val;
+        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
+        break;
+    case 0x0240: /* DIM1 */
+        /* DIM: Device Interrupt Mask Register, CPU1.  */
+        s->cchip.dim[0] = val;
+        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
+        break;
+
+    case 0x0280: /* DIR0 (RO) */
+    case 0x02c0: /* DIR1 (RO) */
+    case 0x0300: /* DRIR (RO) */
+        break;
+
+    case 0x0340:
+        /* PRBEN: Probe Enable Register.  */
+        break;
+
+    case 0x0380: /* IIC0 */
+        s->cchip.iic[0] = val & 0xffffff;
+        break;
+    case 0x03c0: /* IIC1 */
+        s->cchip.iic[1] = val & 0xffffff;
+        break;
+
+    case 0x0400: /* MPR0 */
+    case 0x0440: /* MPR1 */
+    case 0x0480: /* MPR2 */
+    case 0x04c0: /* MPR3 */
+        /* MPR: Memory Programming Register.  */
+        break;
+
+    case 0x0580:
+        /* TTR: TIGbus Timing Register.  */
+        /* All sorts of stuff related to interrupt delivery timings.  */
+        break;
+    case 0x05c0:
+        /* TDR: TIGbug Device Timing Register.  */
+        break;
+
+    case 0x0600:
+        /* DIM2: Device Interrupt Mask Register, CPU2.  */
+        s->cchip.dim[2] = val;
+        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
+        break;
+    case 0x0640:
+        /* DIM3: Device Interrupt Mask Register, CPU3.  */
+        s->cchip.dim[3] = val;
+        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
+        break;
+
+    case 0x0680: /* DIR2 (RO) */
+    case 0x06c0: /* DIR3 (RO) */
+        break;
+
+    case 0x0700: /* IIC2 */
+        s->cchip.iic[2] = val & 0xffffff;
+        break;
+    case 0x0740: /* IIC3 */
+        s->cchip.iic[3] = val & 0xffffff;
+        break;
+
+    case 0x0780:
+        /* PWR: Power Management Control.   */
+        break;
+    
+    case 0x0c00: /* CMONCTLA */
+    case 0x0c40: /* CMONCTLB */
+    case 0x0c80: /* CMONCNT01 */
+    case 0x0cc0: /* CMONCNT23 */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
+        return;
+    }
+}
+
+static void dchip_write(void *opaque, hwaddr addr,
+                        uint64_t val, unsigned size)
+{
+    /* Skip this.  It's all related to DRAM timing and setup.  */
+}
+
+static void pchip_write(void *opaque, hwaddr addr,
+                        uint64_t v32, unsigned size)
+{
+    TyphoonState *s = opaque;
+    uint64_t val, oldval;
+
+    if (addr & 4) {
+        val = v32 << 32 | s->latch_tmp;
+        addr ^= 4;
+    } else {
+        s->latch_tmp = v32;
+        return;
+    }
+
+    switch (addr) {
+    case 0x0000:
+        /* WSBA0: Window Space Base Address Register.  */
+        s->pchip.win[0].base_addr = val;
+        break;
+    case 0x0040:
+        /* WSBA1 */
+        s->pchip.win[1].base_addr = val;
+        break;
+    case 0x0080:
+        /* WSBA2 */
+        s->pchip.win[2].base_addr = val;
+        break;
+    case 0x00c0:
+        /* WSBA3 */
+        s->pchip.win[3].base_addr = val;
+        break;
+
+    case 0x0100:
+        /* WSM0: Window Space Mask Register.  */
+        s->pchip.win[0].mask = val;
+        break;
+    case 0x0140:
+        /* WSM1 */
+        s->pchip.win[1].mask = val;
+        break;
+    case 0x0180:
+        /* WSM2 */
+        s->pchip.win[2].mask = val;
+        break;
+    case 0x01c0:
+        /* WSM3 */
+        s->pchip.win[3].mask = val;
+        break;
+
+    case 0x0200:
+        /* TBA0: Translated Base Address Register.  */
+        s->pchip.win[0].translated_base_pfn = val >> 10;
+        break;
+    case 0x0240:
+        /* TBA1 */
+        s->pchip.win[1].translated_base_pfn = val >> 10;
+        break;
+    case 0x0280:
+        /* TBA2 */
+        s->pchip.win[2].translated_base_pfn = val >> 10;
+        break;
+    case 0x02c0:
+        /* TBA3 */
+        s->pchip.win[3].translated_base_pfn = val >> 10;
+        break;
+
+    case 0x0300:
+        /* PCTL: Pchip Control Register.  */
+        oldval = s->pchip.ctl;
+        oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
+        oldval |= val & 0x00001cff0fc7ffull;
+
+        s->pchip.ctl = oldval;
+        break;
+
+    case 0x0340:
+        /* PLAT: Pchip Master Latency Register.  */
+        break;
+    case 0x03c0:
+        /* PERROR: Pchip Error Register.  */
+        break;
+    case 0x0400:
+        /* PERRMASK: Pchip Error Mask Register.  */
+        break;
+    case 0x0440:
+        /* PERRSET: Pchip Error Set Register.  */
+        break;
+
+    case 0x0480:
+        /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
+        break;
+
+    case 0x04c0:
+        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
+        break;
+
+    case 0x0500:
+        /* PMONCTL */
+    case 0x0540:
+        /* PMONCNT */
+    case 0x0800:
+        /* SPRST */
+        break;
+
+    default:
+        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
+        return;
+    }
+}
+
+static const MemoryRegionOps cchip_ops = {
+    .read = cchip_read,
+    .write = cchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static const MemoryRegionOps dchip_ops = {
+    .read = dchip_read,
+    .write = dchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+};
+
+static const MemoryRegionOps pchip_ops = {
+    .read = pchip_read,
+    .write = pchip_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,  /* ??? Should be 8.  */
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void typhoon_set_irq(void *opaque, int irq, int level)
+{
+    TyphoonState *s = opaque;
+    uint64_t drir;
+    int i;
+
+    /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
+    drir = s->cchip.drir;
+    if (level) {
+        drir |= 1ull << irq;
+    } else {
+        drir &= ~(1ull << irq);
+    }
+    s->cchip.drir = drir;
+
+    for (i = 0; i < 4; ++i) {
+        cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
+    }
+}
+
+static void typhoon_set_isa_irq(void *opaque, int irq, int level)
+{
+    typhoon_set_irq(opaque, 55, level);
+}
+
+static void typhoon_set_timer_irq(void *opaque, int irq, int level)
+{
+    TyphoonState *s = opaque;
+    int i;
+
+    /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
+       and so we don't have to worry about missing interrupts just
+       because we never actually ACK the interrupt.  Just ignore any
+       case of the interrupt level going low.  */
+    if (level == 0) {
+        return;
+    }
+
+    /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
+    for (i = 0; i < 4; ++i) {
+        AlphaCPU *cpu = s->cchip.cpu[i];
+        if (cpu != NULL) {
+            uint32_t iic = s->cchip.iic[i];
+
+            /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
+               Bit 24 is the OverFlow bit, RO, and set when the count
+               decrements past 0.  When is OF cleared?  My guess is that
+               OF is actually cleared when the IIC is written, and that
+               the ICNT field always decrements.  At least, that's an
+               interpretation that makes sense, and "allows the CPU to
+               determine exactly how mant interval timer ticks were
+               skipped".  At least within the next 4M ticks...  */
+
+            iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
+            s->cchip.iic[i] = iic;
+
+            if (iic & 0x1000000) {
+                /* Set the ITI bit for this cpu.  */
+                s->cchip.misc |= 1 << (i + 4);
+                /* And signal the interrupt.  */
+                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
+            }
+        }
+    }
+}
+
+static void typhoon_alarm_timer(void *opaque)
+{
+    TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
+    int cpu = (uintptr_t)opaque & 3;
+
+    /* Set the ITI bit for this cpu.  */
+    s->cchip.misc |= 1 << (cpu + 4);
+    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
+}
+
+PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
+                     qemu_irq *p_rtc_irq,
+                     AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
+{
+    const uint64_t MB = 1024 * 1024;
+    const uint64_t GB = 1024 * MB;
+    MemoryRegion *addr_space = get_system_memory();
+    MemoryRegion *addr_space_io = get_system_io();
+    DeviceState *dev;
+    TyphoonState *s;
+    PCIHostState *phb;
+    PCIBus *b;
+    int i;
+
+    dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+
+    s = TYPHOON_PCI_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
+
+    /* Remember the CPUs so that we can deliver interrupts to them.  */
+    for (i = 0; i < 4; i++) {
+        AlphaCPU *cpu = cpus[i];
+        s->cchip.cpu[i] = cpu;
+        if (cpu != NULL) {
+            cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
+                                                 typhoon_alarm_timer,
+                                                 (void *)((uintptr_t)s + i));
+        }
+    }
+
+    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
+
+    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
+       but the address space hole reserved at this point is 8TB.  */
+    memory_region_init_ram(&s->ram_region, "ram", ram_size);
+    vmstate_register_ram_global(&s->ram_region);
+    memory_region_add_subregion(addr_space, 0, &s->ram_region);
+
+    /* TIGbus, 0x801.0000.0000, 1GB.  */
+    /* ??? The TIGbus is used for delivering interrupts, and access to
+       the flash ROM.  I'm not sure that we need to implement it at all.  */
+
+    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
+    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x80180000000ULL,
+                                &s->pchip.region);
+
+    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
+    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
+                                &s->cchip.region);
+
+    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
+    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
+    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
+                                &s->dchip_region);
+
+    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
+    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
+    memory_region_add_subregion(addr_space, 0x80000000000ULL,
+                                &s->pchip.reg_mem);
+
+    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
+    /* ??? Ideally we drop the "system" i/o space on the floor and give the
+       PCI subsystem the full address space reserved by the chipset.
+       We can't do that until the MEM and IO paths in memory.c are unified.  */
+    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
+                          "pci0-io", 32*MB);
+    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
+                                &s->pchip.reg_io);
+
+    b = pci_register_bus(dev, "pci",
+                         typhoon_set_irq, sys_map_irq, s,
+                         &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
+    phb->bus = b;
+
+    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
+    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
+                          "pci0-iack", 64*MB);
+    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
+                                &s->pchip.reg_iack);
+
+    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
+    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
+                          "pci0-conf", 16*MB);
+    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
+                                &s->pchip.reg_conf);
+
+    /* For the record, these are the mappings for the second PCI bus.
+       We can get away with not implementing them because we indicate
+       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
+    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
+    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
+    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
+    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
+    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
+
+    /* Init the ISA bus.  */
+    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
+    {
+        qemu_irq isa_pci_irq, *isa_irqs;
+
+        *isa_bus = isa_bus_new(NULL, addr_space_io);
+        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
+        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
+        isa_bus_irqs(*isa_bus, isa_irqs);
+    }
+
+    return b;
+}
+
+static int typhoon_pcihost_init(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = typhoon_pcihost_init;
+    dc->no_user = 1;
+}
+
+static const TypeInfo typhoon_pcihost_info = {
+    .name          = TYPE_TYPHOON_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(TyphoonState),
+    .class_init    = typhoon_pcihost_class_init,
+};
+
+static void typhoon_register_types(void)
+{
+    type_register_static(&typhoon_pcihost_info);
+}
+
+type_init(typhoon_register_types)
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
deleted file mode 100644 (file)
index 41a0ebc..0000000
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation.
- *
- * Written by Richard Henderson.
- *
- * This work is licensed under the GNU GPL license version 2 or later.
- */
-
-#include "cpu.h"
-#include "exec/exec-all.h"
-#include "hw/hw.h"
-#include "hw/arm/devices.h"
-#include "sysemu/sysemu.h"
-#include "hw/alpha_sys.h"
-#include "exec/address-spaces.h"
-
-
-#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
-
-typedef struct TyphoonCchip {
-    MemoryRegion region;
-    uint64_t misc;
-    uint64_t drir;
-    uint64_t dim[4];
-    uint32_t iic[4];
-    AlphaCPU *cpu[4];
-} TyphoonCchip;
-
-typedef struct TyphoonWindow {
-    uint32_t base_addr;
-    uint32_t mask;
-    uint32_t translated_base_pfn;
-} TyphoonWindow;
-typedef struct TyphoonPchip {
-    MemoryRegion region;
-    MemoryRegion reg_iack;
-    MemoryRegion reg_mem;
-    MemoryRegion reg_io;
-    MemoryRegion reg_conf;
-    uint64_t ctl;
-    TyphoonWindow win[4];
-} TyphoonPchip;
-
-#define TYPHOON_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
-
-typedef struct TyphoonState {
-    PCIHostState parent_obj;
-
-    TyphoonCchip cchip;
-    TyphoonPchip pchip;
-    MemoryRegion dchip_region;
-    MemoryRegion ram_region;
-
-    /* QEMU emulation state.  */
-    uint32_t latch_tmp;
-} TyphoonState;
-
-/* Called when one of DRIR or DIM changes.  */
-static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
-{
-    /* If there are any non-masked interrupts, tell the cpu.  */
-    if (cpu != NULL) {
-        CPUState *cs = CPU(cpu);
-        if (req) {
-            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
-        } else {
-            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
-        }
-    }
-}
-
-static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
-{
-    CPUAlphaState *env = cpu_single_env;
-    TyphoonState *s = opaque;
-    CPUState *cpu;
-    uint64_t ret = 0;
-
-    if (addr & 4) {
-        return s->latch_tmp;
-    }
-
-    switch (addr) {
-    case 0x0000:
-        /* CSC: Cchip System Configuration Register.  */
-        /* All sorts of data here; probably the only thing relevant is
-           PIP<14> Pchip 1 Present = 0.  */
-        break;
-
-    case 0x0040:
-        /* MTR: Memory Timing Register.  */
-        /* All sorts of stuff related to real DRAM.  */
-        break;
-
-    case 0x0080:
-        /* MISC: Miscellaneous Register.  */
-        cpu = ENV_GET_CPU(env);
-        ret = s->cchip.misc | (cpu->cpu_index & 3);
-        break;
-
-    case 0x00c0:
-        /* MPD: Memory Presence Detect Register.  */
-        break;
-
-    case 0x0100: /* AAR0 */
-    case 0x0140: /* AAR1 */
-    case 0x0180: /* AAR2 */
-    case 0x01c0: /* AAR3 */
-        /* AAR: Array Address Register.  */
-        /* All sorts of information about DRAM.  */
-        break;
-
-    case 0x0200:
-        /* DIM0: Device Interrupt Mask Register, CPU0.  */
-        ret = s->cchip.dim[0];
-        break;
-    case 0x0240:
-        /* DIM1: Device Interrupt Mask Register, CPU1.  */
-        ret = s->cchip.dim[1];
-        break;
-    case 0x0280:
-        /* DIR0: Device Interrupt Request Register, CPU0.  */
-        ret = s->cchip.dim[0] & s->cchip.drir;
-        break;
-    case 0x02c0:
-        /* DIR1: Device Interrupt Request Register, CPU1.  */
-        ret = s->cchip.dim[1] & s->cchip.drir;
-        break;
-    case 0x0300:
-        /* DRIR: Device Raw Interrupt Request Register.  */
-        ret = s->cchip.drir;
-        break;
-
-    case 0x0340:
-        /* PRBEN: Probe Enable Register.  */
-        break;
-
-    case 0x0380:
-        /* IIC0: Interval Ignore Count Register, CPU0.  */
-        ret = s->cchip.iic[0];
-        break;
-    case 0x03c0:
-        /* IIC1: Interval Ignore Count Register, CPU1.  */
-        ret = s->cchip.iic[1];
-        break;
-
-    case 0x0400: /* MPR0 */
-    case 0x0440: /* MPR1 */
-    case 0x0480: /* MPR2 */
-    case 0x04c0: /* MPR3 */
-        /* MPR: Memory Programming Register.  */
-        break;
-
-    case 0x0580:
-        /* TTR: TIGbus Timing Register.  */
-        /* All sorts of stuff related to interrupt delivery timings.  */
-        break;
-    case 0x05c0:
-        /* TDR: TIGbug Device Timing Register.  */
-        break;
-
-    case 0x0600:
-        /* DIM2: Device Interrupt Mask Register, CPU2.  */
-        ret = s->cchip.dim[2];
-        break;
-    case 0x0640:
-        /* DIM3: Device Interrupt Mask Register, CPU3.  */
-        ret = s->cchip.dim[3];
-        break;
-    case 0x0680:
-        /* DIR2: Device Interrupt Request Register, CPU2.  */
-        ret = s->cchip.dim[2] & s->cchip.drir;
-        break;
-    case 0x06c0:
-        /* DIR3: Device Interrupt Request Register, CPU3.  */
-        ret = s->cchip.dim[3] & s->cchip.drir;
-        break;
-
-    case 0x0700:
-        /* IIC2: Interval Ignore Count Register, CPU2.  */
-        ret = s->cchip.iic[2];
-        break;
-    case 0x0740:
-        /* IIC3: Interval Ignore Count Register, CPU3.  */
-        ret = s->cchip.iic[3];
-        break;
-
-    case 0x0780:
-        /* PWR: Power Management Control.   */
-        break;
-    
-    case 0x0c00: /* CMONCTLA */
-    case 0x0c40: /* CMONCTLB */
-    case 0x0c80: /* CMONCNT01 */
-    case 0x0cc0: /* CMONCNT23 */
-        break;
-
-    default:
-        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
-        return -1;
-    }
-
-    s->latch_tmp = ret >> 32;
-    return ret;
-}
-
-static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
-{
-    /* Skip this.  It's all related to DRAM timing and setup.  */
-    return 0;
-}
-
-static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
-{
-    TyphoonState *s = opaque;
-    uint64_t ret = 0;
-
-    if (addr & 4) {
-        return s->latch_tmp;
-    }
-
-    switch (addr) {
-    case 0x0000:
-        /* WSBA0: Window Space Base Address Register.  */
-        ret = s->pchip.win[0].base_addr;
-        break;
-    case 0x0040:
-        /* WSBA1 */
-        ret = s->pchip.win[1].base_addr;
-        break;
-    case 0x0080:
-        /* WSBA2 */
-        ret = s->pchip.win[2].base_addr;
-        break;
-    case 0x00c0:
-        /* WSBA3 */
-        ret = s->pchip.win[3].base_addr;
-        break;
-
-    case 0x0100:
-        /* WSM0: Window Space Mask Register.  */
-        ret = s->pchip.win[0].mask;
-        break;
-    case 0x0140:
-        /* WSM1 */
-        ret = s->pchip.win[1].mask;
-        break;
-    case 0x0180:
-        /* WSM2 */
-        ret = s->pchip.win[2].mask;
-        break;
-    case 0x01c0:
-        /* WSM3 */
-        ret = s->pchip.win[3].mask;
-        break;
-
-    case 0x0200:
-        /* TBA0: Translated Base Address Register.  */
-        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
-        break;
-    case 0x0240:
-        /* TBA1 */
-        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
-        break;
-    case 0x0280:
-        /* TBA2 */
-        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
-        break;
-    case 0x02c0:
-        /* TBA3 */
-        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
-        break;
-
-    case 0x0300:
-        /* PCTL: Pchip Control Register.  */
-        ret = s->pchip.ctl;
-        break;
-    case 0x0340:
-        /* PLAT: Pchip Master Latency Register.  */
-        break;
-    case 0x03c0:
-        /* PERROR: Pchip Error Register.  */
-        break;
-    case 0x0400:
-        /* PERRMASK: Pchip Error Mask Register.  */
-        break;
-    case 0x0440:
-        /* PERRSET: Pchip Error Set Register.  */
-        break;
-    case 0x0480:
-        /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
-        break;
-    case 0x04c0:
-        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
-        break;
-    case 0x0500: /* PMONCTL */
-    case 0x0540: /* PMONCNT */
-    case 0x0800: /* SPRST */
-        break;
-
-    default:
-        cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
-        return -1;
-    }
-
-    s->latch_tmp = ret >> 32;
-    return ret;
-}
-
-static void cchip_write(void *opaque, hwaddr addr,
-                        uint64_t v32, unsigned size)
-{
-    TyphoonState *s = opaque;
-    uint64_t val, oldval, newval;
-
-    if (addr & 4) {
-        val = v32 << 32 | s->latch_tmp;
-        addr ^= 4;
-    } else {
-        s->latch_tmp = v32;
-        return;
-    }
-
-    switch (addr) {
-    case 0x0000:
-        /* CSC: Cchip System Configuration Register.  */
-        /* All sorts of data here; nothing relevant RW.  */
-        break;
-
-    case 0x0040:
-        /* MTR: Memory Timing Register.  */
-        /* All sorts of stuff related to real DRAM.  */
-        break;
-
-    case 0x0080:
-        /* MISC: Miscellaneous Register.  */
-        newval = oldval = s->cchip.misc;
-        newval &= ~(val & 0x10000ff0);     /* W1C fields */
-        if (val & 0x100000) {
-            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
-        } else {
-            newval |= val & 0x00f00000;    /* ABT field is W1S */
-            if ((newval & 0xf0000) == 0) {
-                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
-            }
-        }
-        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
-
-        newval &= ~0xf0000000000ull;       /* WO and RW fields */
-        newval |= val & 0xf0000000000ull;
-        s->cchip.misc = newval;
-
-        /* Pass on changes to IPI and ITI state.  */
-        if ((newval ^ oldval) & 0xff0) {
-            int i;
-            for (i = 0; i < 4; ++i) {
-                AlphaCPU *cpu = s->cchip.cpu[i];
-                if (cpu != NULL) {
-                    CPUState *cs = CPU(cpu);
-                    /* IPI can be either cleared or set by the write.  */
-                    if (newval & (1 << (i + 8))) {
-                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
-                    } else {
-                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
-                    }
-
-                    /* ITI can only be cleared by the write.  */
-                    if ((newval & (1 << (i + 4))) == 0) {
-                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
-                    }
-                }
-            }
-        }
-        break;
-
-    case 0x00c0:
-        /* MPD: Memory Presence Detect Register.  */
-        break;
-
-    case 0x0100: /* AAR0 */
-    case 0x0140: /* AAR1 */
-    case 0x0180: /* AAR2 */
-    case 0x01c0: /* AAR3 */
-        /* AAR: Array Address Register.  */
-        /* All sorts of information about DRAM.  */
-        break;
-
-    case 0x0200: /* DIM0 */
-        /* DIM: Device Interrupt Mask Register, CPU0.  */
-        s->cchip.dim[0] = val;
-        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
-        break;
-    case 0x0240: /* DIM1 */
-        /* DIM: Device Interrupt Mask Register, CPU1.  */
-        s->cchip.dim[0] = val;
-        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
-        break;
-
-    case 0x0280: /* DIR0 (RO) */
-    case 0x02c0: /* DIR1 (RO) */
-    case 0x0300: /* DRIR (RO) */
-        break;
-
-    case 0x0340:
-        /* PRBEN: Probe Enable Register.  */
-        break;
-
-    case 0x0380: /* IIC0 */
-        s->cchip.iic[0] = val & 0xffffff;
-        break;
-    case 0x03c0: /* IIC1 */
-        s->cchip.iic[1] = val & 0xffffff;
-        break;
-
-    case 0x0400: /* MPR0 */
-    case 0x0440: /* MPR1 */
-    case 0x0480: /* MPR2 */
-    case 0x04c0: /* MPR3 */
-        /* MPR: Memory Programming Register.  */
-        break;
-
-    case 0x0580:
-        /* TTR: TIGbus Timing Register.  */
-        /* All sorts of stuff related to interrupt delivery timings.  */
-        break;
-    case 0x05c0:
-        /* TDR: TIGbug Device Timing Register.  */
-        break;
-
-    case 0x0600:
-        /* DIM2: Device Interrupt Mask Register, CPU2.  */
-        s->cchip.dim[2] = val;
-        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
-        break;
-    case 0x0640:
-        /* DIM3: Device Interrupt Mask Register, CPU3.  */
-        s->cchip.dim[3] = val;
-        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
-        break;
-
-    case 0x0680: /* DIR2 (RO) */
-    case 0x06c0: /* DIR3 (RO) */
-        break;
-
-    case 0x0700: /* IIC2 */
-        s->cchip.iic[2] = val & 0xffffff;
-        break;
-    case 0x0740: /* IIC3 */
-        s->cchip.iic[3] = val & 0xffffff;
-        break;
-
-    case 0x0780:
-        /* PWR: Power Management Control.   */
-        break;
-    
-    case 0x0c00: /* CMONCTLA */
-    case 0x0c40: /* CMONCTLB */
-    case 0x0c80: /* CMONCNT01 */
-    case 0x0cc0: /* CMONCNT23 */
-        break;
-
-    default:
-        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
-        return;
-    }
-}
-
-static void dchip_write(void *opaque, hwaddr addr,
-                        uint64_t val, unsigned size)
-{
-    /* Skip this.  It's all related to DRAM timing and setup.  */
-}
-
-static void pchip_write(void *opaque, hwaddr addr,
-                        uint64_t v32, unsigned size)
-{
-    TyphoonState *s = opaque;
-    uint64_t val, oldval;
-
-    if (addr & 4) {
-        val = v32 << 32 | s->latch_tmp;
-        addr ^= 4;
-    } else {
-        s->latch_tmp = v32;
-        return;
-    }
-
-    switch (addr) {
-    case 0x0000:
-        /* WSBA0: Window Space Base Address Register.  */
-        s->pchip.win[0].base_addr = val;
-        break;
-    case 0x0040:
-        /* WSBA1 */
-        s->pchip.win[1].base_addr = val;
-        break;
-    case 0x0080:
-        /* WSBA2 */
-        s->pchip.win[2].base_addr = val;
-        break;
-    case 0x00c0:
-        /* WSBA3 */
-        s->pchip.win[3].base_addr = val;
-        break;
-
-    case 0x0100:
-        /* WSM0: Window Space Mask Register.  */
-        s->pchip.win[0].mask = val;
-        break;
-    case 0x0140:
-        /* WSM1 */
-        s->pchip.win[1].mask = val;
-        break;
-    case 0x0180:
-        /* WSM2 */
-        s->pchip.win[2].mask = val;
-        break;
-    case 0x01c0:
-        /* WSM3 */
-        s->pchip.win[3].mask = val;
-        break;
-
-    case 0x0200:
-        /* TBA0: Translated Base Address Register.  */
-        s->pchip.win[0].translated_base_pfn = val >> 10;
-        break;
-    case 0x0240:
-        /* TBA1 */
-        s->pchip.win[1].translated_base_pfn = val >> 10;
-        break;
-    case 0x0280:
-        /* TBA2 */
-        s->pchip.win[2].translated_base_pfn = val >> 10;
-        break;
-    case 0x02c0:
-        /* TBA3 */
-        s->pchip.win[3].translated_base_pfn = val >> 10;
-        break;
-
-    case 0x0300:
-        /* PCTL: Pchip Control Register.  */
-        oldval = s->pchip.ctl;
-        oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
-        oldval |= val & 0x00001cff0fc7ffull;
-
-        s->pchip.ctl = oldval;
-        break;
-
-    case 0x0340:
-        /* PLAT: Pchip Master Latency Register.  */
-        break;
-    case 0x03c0:
-        /* PERROR: Pchip Error Register.  */
-        break;
-    case 0x0400:
-        /* PERRMASK: Pchip Error Mask Register.  */
-        break;
-    case 0x0440:
-        /* PERRSET: Pchip Error Set Register.  */
-        break;
-
-    case 0x0480:
-        /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
-        break;
-
-    case 0x04c0:
-        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
-        break;
-
-    case 0x0500:
-        /* PMONCTL */
-    case 0x0540:
-        /* PMONCNT */
-    case 0x0800:
-        /* SPRST */
-        break;
-
-    default:
-        cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
-        return;
-    }
-}
-
-static const MemoryRegionOps cchip_ops = {
-    .read = cchip_read,
-    .write = cchip_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,  /* ??? Should be 8.  */
-        .max_access_size = 8,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static const MemoryRegionOps dchip_ops = {
-    .read = dchip_read,
-    .write = dchip_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,  /* ??? Should be 8.  */
-        .max_access_size = 8,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 8,
-    },
-};
-
-static const MemoryRegionOps pchip_ops = {
-    .read = pchip_read,
-    .write = pchip_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,  /* ??? Should be 8.  */
-        .max_access_size = 8,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static void typhoon_set_irq(void *opaque, int irq, int level)
-{
-    TyphoonState *s = opaque;
-    uint64_t drir;
-    int i;
-
-    /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
-    drir = s->cchip.drir;
-    if (level) {
-        drir |= 1ull << irq;
-    } else {
-        drir &= ~(1ull << irq);
-    }
-    s->cchip.drir = drir;
-
-    for (i = 0; i < 4; ++i) {
-        cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
-    }
-}
-
-static void typhoon_set_isa_irq(void *opaque, int irq, int level)
-{
-    typhoon_set_irq(opaque, 55, level);
-}
-
-static void typhoon_set_timer_irq(void *opaque, int irq, int level)
-{
-    TyphoonState *s = opaque;
-    int i;
-
-    /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
-       and so we don't have to worry about missing interrupts just
-       because we never actually ACK the interrupt.  Just ignore any
-       case of the interrupt level going low.  */
-    if (level == 0) {
-        return;
-    }
-
-    /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
-    for (i = 0; i < 4; ++i) {
-        AlphaCPU *cpu = s->cchip.cpu[i];
-        if (cpu != NULL) {
-            uint32_t iic = s->cchip.iic[i];
-
-            /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
-               Bit 24 is the OverFlow bit, RO, and set when the count
-               decrements past 0.  When is OF cleared?  My guess is that
-               OF is actually cleared when the IIC is written, and that
-               the ICNT field always decrements.  At least, that's an
-               interpretation that makes sense, and "allows the CPU to
-               determine exactly how mant interval timer ticks were
-               skipped".  At least within the next 4M ticks...  */
-
-            iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
-            s->cchip.iic[i] = iic;
-
-            if (iic & 0x1000000) {
-                /* Set the ITI bit for this cpu.  */
-                s->cchip.misc |= 1 << (i + 4);
-                /* And signal the interrupt.  */
-                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
-            }
-        }
-    }
-}
-
-static void typhoon_alarm_timer(void *opaque)
-{
-    TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
-    int cpu = (uintptr_t)opaque & 3;
-
-    /* Set the ITI bit for this cpu.  */
-    s->cchip.misc |= 1 << (cpu + 4);
-    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
-}
-
-PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
-                     qemu_irq *p_rtc_irq,
-                     AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
-{
-    const uint64_t MB = 1024 * 1024;
-    const uint64_t GB = 1024 * MB;
-    MemoryRegion *addr_space = get_system_memory();
-    MemoryRegion *addr_space_io = get_system_io();
-    DeviceState *dev;
-    TyphoonState *s;
-    PCIHostState *phb;
-    PCIBus *b;
-    int i;
-
-    dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-
-    s = TYPHOON_PCI_HOST_BRIDGE(dev);
-    phb = PCI_HOST_BRIDGE(dev);
-
-    /* Remember the CPUs so that we can deliver interrupts to them.  */
-    for (i = 0; i < 4; i++) {
-        AlphaCPU *cpu = cpus[i];
-        s->cchip.cpu[i] = cpu;
-        if (cpu != NULL) {
-            cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
-                                                 typhoon_alarm_timer,
-                                                 (void *)((uintptr_t)s + i));
-        }
-    }
-
-    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
-
-    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
-       but the address space hole reserved at this point is 8TB.  */
-    memory_region_init_ram(&s->ram_region, "ram", ram_size);
-    vmstate_register_ram_global(&s->ram_region);
-    memory_region_add_subregion(addr_space, 0, &s->ram_region);
-
-    /* TIGbus, 0x801.0000.0000, 1GB.  */
-    /* ??? The TIGbus is used for delivering interrupts, and access to
-       the flash ROM.  I'm not sure that we need to implement it at all.  */
-
-    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
-    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
-    memory_region_add_subregion(addr_space, 0x80180000000ULL,
-                                &s->pchip.region);
-
-    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
-    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
-    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
-                                &s->cchip.region);
-
-    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
-    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
-    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
-                                &s->dchip_region);
-
-    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
-    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
-    memory_region_add_subregion(addr_space, 0x80000000000ULL,
-                                &s->pchip.reg_mem);
-
-    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
-    /* ??? Ideally we drop the "system" i/o space on the floor and give the
-       PCI subsystem the full address space reserved by the chipset.
-       We can't do that until the MEM and IO paths in memory.c are unified.  */
-    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
-                          "pci0-io", 32*MB);
-    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
-                                &s->pchip.reg_io);
-
-    b = pci_register_bus(dev, "pci",
-                         typhoon_set_irq, sys_map_irq, s,
-                         &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
-    phb->bus = b;
-
-    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
-    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
-                          "pci0-iack", 64*MB);
-    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
-                                &s->pchip.reg_iack);
-
-    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
-    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
-                          "pci0-conf", 16*MB);
-    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
-                                &s->pchip.reg_conf);
-
-    /* For the record, these are the mappings for the second PCI bus.
-       We can get away with not implementing them because we indicate
-       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
-    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
-    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
-    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
-    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
-    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
-
-    /* Init the ISA bus.  */
-    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
-    {
-        qemu_irq isa_pci_irq, *isa_irqs;
-
-        *isa_bus = isa_bus_new(NULL, addr_space_io);
-        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
-        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
-        isa_bus_irqs(*isa_bus, isa_irqs);
-    }
-
-    return b;
-}
-
-static int typhoon_pcihost_init(SysBusDevice *dev)
-{
-    return 0;
-}
-
-static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = typhoon_pcihost_init;
-    dc->no_user = 1;
-}
-
-static const TypeInfo typhoon_pcihost_info = {
-    .name          = TYPE_TYPHOON_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(TyphoonState),
-    .class_init    = typhoon_pcihost_class_init,
-};
-
-static void typhoon_register_types(void)
-{
-    type_register_static(&typhoon_pcihost_info);
-}
-
-type_init(typhoon_register_types)
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
deleted file mode 100644 (file)
index fe15ae8..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * QEMU Ultrasparc APB PCI host
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * 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.
- */
-
-/* XXX This file and most of its contents are somewhat misnamed.  The
-   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
-   the secondary PCI bridge.  */
-
-#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "hw/pci/pci_bridge.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci-host/apb.h"
-#include "sysemu/sysemu.h"
-#include "exec/address-spaces.h"
-
-/* debug APB */
-//#define DEBUG_APB
-
-#ifdef DEBUG_APB
-#define APB_DPRINTF(fmt, ...) \
-do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define APB_DPRINTF(fmt, ...)
-#endif
-
-/*
- * Chipset docs:
- * PBM: "UltraSPARC IIi User's Manual",
- * http://www.sun.com/processors/manuals/805-0087.pdf
- *
- * APB: "Advanced PCI Bridge (APB) User's Manual",
- * http://www.sun.com/processors/manuals/805-1251.pdf
- */
-
-#define PBM_PCI_IMR_MASK    0x7fffffff
-#define PBM_PCI_IMR_ENABLED 0x80000000
-
-#define POR          (1 << 31)
-#define SOFT_POR     (1 << 30)
-#define SOFT_XIR     (1 << 29)
-#define BTN_POR      (1 << 28)
-#define BTN_XIR      (1 << 27)
-#define RESET_MASK   0xf8000000
-#define RESET_WCMASK 0x98000000
-#define RESET_WMASK  0x60000000
-
-#define MAX_IVEC 0x30
-
-typedef struct APBState {
-    SysBusDevice busdev;
-    PCIBus      *bus;
-    MemoryRegion apb_config;
-    MemoryRegion pci_config;
-    MemoryRegion pci_mmio;
-    MemoryRegion pci_ioport;
-    uint32_t iommu[4];
-    uint32_t pci_control[16];
-    uint32_t pci_irq_map[8];
-    uint32_t obio_irq_map[32];
-    qemu_irq *pbm_irqs;
-    qemu_irq *ivec_irqs;
-    uint32_t reset_control;
-    unsigned int nr_resets;
-} APBState;
-
-static void pci_apb_set_irq(void *opaque, int irq_num, int level);
-
-static void apb_config_writel (void *opaque, hwaddr addr,
-                               uint64_t val, unsigned size)
-{
-    APBState *s = opaque;
-
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
-
-    switch (addr & 0xffff) {
-    case 0x30 ... 0x4f: /* DMA error registers */
-        /* XXX: not implemented yet */
-        break;
-    case 0x200 ... 0x20b: /* IOMMU */
-        s->iommu[(addr & 0xf) >> 2] = val;
-        break;
-    case 0x20c ... 0x3ff: /* IOMMU flush */
-        break;
-    case 0xc00 ... 0xc3f: /* PCI interrupt control */
-        if (addr & 4) {
-            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
-            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
-        }
-        break;
-    case 0x1000 ... 0x1080: /* OBIO interrupt control */
-        if (addr & 4) {
-            s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
-            s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
-        }
-        break;
-    case 0x1400 ... 0x143f: /* PCI interrupt clear */
-        if (addr & 4) {
-            pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0);
-        }
-        break;
-    case 0x1800 ... 0x1860: /* OBIO interrupt clear */
-        if (addr & 4) {
-            pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0);
-        }
-        break;
-    case 0x2000 ... 0x202f: /* PCI control */
-        s->pci_control[(addr & 0x3f) >> 2] = val;
-        break;
-    case 0xf020 ... 0xf027: /* Reset control */
-        if (addr & 4) {
-            val &= RESET_MASK;
-            s->reset_control &= ~(val & RESET_WCMASK);
-            s->reset_control |= val & RESET_WMASK;
-            if (val & SOFT_POR) {
-                s->nr_resets = 0;
-                qemu_system_reset_request();
-            } else if (val & SOFT_XIR) {
-                qemu_system_reset_request();
-            }
-        }
-        break;
-    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
-    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
-    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
-    case 0xf000 ... 0xf01f: /* FFB config, memory control */
-        /* we don't care */
-    default:
-        break;
-    }
-}
-
-static uint64_t apb_config_readl (void *opaque,
-                                  hwaddr addr, unsigned size)
-{
-    APBState *s = opaque;
-    uint32_t val;
-
-    switch (addr & 0xffff) {
-    case 0x30 ... 0x4f: /* DMA error registers */
-        val = 0;
-        /* XXX: not implemented yet */
-        break;
-    case 0x200 ... 0x20b: /* IOMMU */
-        val = s->iommu[(addr & 0xf) >> 2];
-        break;
-    case 0x20c ... 0x3ff: /* IOMMU flush */
-        val = 0;
-        break;
-    case 0xc00 ... 0xc3f: /* PCI interrupt control */
-        if (addr & 4) {
-            val = s->pci_irq_map[(addr & 0x3f) >> 3];
-        } else {
-            val = 0;
-        }
-        break;
-    case 0x1000 ... 0x1080: /* OBIO interrupt control */
-        if (addr & 4) {
-            val = s->obio_irq_map[(addr & 0xff) >> 3];
-        } else {
-            val = 0;
-        }
-        break;
-    case 0x2000 ... 0x202f: /* PCI control */
-        val = s->pci_control[(addr & 0x3f) >> 2];
-        break;
-    case 0xf020 ... 0xf027: /* Reset control */
-        if (addr & 4) {
-            val = s->reset_control;
-        } else {
-            val = 0;
-        }
-        break;
-    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
-    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
-    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
-    case 0xf000 ... 0xf01f: /* FFB config, memory control */
-        /* we don't care */
-    default:
-        val = 0;
-        break;
-    }
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, val);
-
-    return val;
-}
-
-static const MemoryRegionOps apb_config_ops = {
-    .read = apb_config_readl,
-    .write = apb_config_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void apb_pci_config_write(void *opaque, hwaddr addr,
-                                 uint64_t val, unsigned size)
-{
-    APBState *s = opaque;
-
-    val = qemu_bswap_len(val, size);
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
-    pci_data_write(s->bus, addr, val, size);
-}
-
-static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
-                                    unsigned size)
-{
-    uint32_t ret;
-    APBState *s = opaque;
-
-    ret = pci_data_read(s->bus, addr, size);
-    ret = qemu_bswap_len(ret, size);
-    APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
-    return ret;
-}
-
-static void pci_apb_iowriteb (void *opaque, hwaddr addr,
-                                  uint32_t val)
-{
-    cpu_outb(addr & IOPORTS_MASK, val);
-}
-
-static void pci_apb_iowritew (void *opaque, hwaddr addr,
-                                  uint32_t val)
-{
-    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
-}
-
-static void pci_apb_iowritel (void *opaque, hwaddr addr,
-                                uint32_t val)
-{
-    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
-}
-
-static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = cpu_inb(addr & IOPORTS_MASK);
-    return val;
-}
-
-static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
-    return val;
-}
-
-static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
-{
-    uint32_t val;
-
-    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
-    return val;
-}
-
-static const MemoryRegionOps pci_ioport_ops = {
-    .old_mmio = {
-        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
-        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* The APB host has an IRQ line for each IRQ line of each slot.  */
-static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
-}
-
-static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    int bus_offset;
-    if (pci_dev->devfn & 1)
-        bus_offset = 16;
-    else
-        bus_offset = 0;
-    return bus_offset + irq_num;
-}
-
-static void pci_apb_set_irq(void *opaque, int irq_num, int level)
-{
-    APBState *s = opaque;
-
-    /* PCI IRQ map onto the first 32 INO.  */
-    if (irq_num < 32) {
-        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
-            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
-            qemu_set_irq(s->ivec_irqs[irq_num], level);
-        } else {
-            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
-            qemu_irq_lower(s->ivec_irqs[irq_num]);
-        }
-    } else {
-        /* OBIO IRQ map onto the next 16 INO.  */
-        if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
-            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
-            qemu_set_irq(s->ivec_irqs[irq_num], level);
-        } else {
-            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
-            qemu_irq_lower(s->ivec_irqs[irq_num]);
-        }
-    }
-}
-
-static int apb_pci_bridge_initfn(PCIDevice *dev)
-{
-    int rc;
-
-    rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
-    if (rc < 0) {
-        return rc;
-    }
-
-    /*
-     * command register:
-     * According to PCI bridge spec, after reset
-     *   bus master bit is off
-     *   memory space enable bit is off
-     * According to manual (805-1251.pdf).
-     *   the reset value should be zero unless the boot pin is tied high
-     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
-     */
-    pci_set_word(dev->config + PCI_COMMAND,
-                 PCI_COMMAND_MEMORY);
-    pci_set_word(dev->config + PCI_STATUS,
-                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
-                 PCI_STATUS_DEVSEL_MEDIUM);
-    return 0;
-}
-
-PCIBus *pci_apb_init(hwaddr special_base,
-                     hwaddr mem_base,
-                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
-                     qemu_irq **pbm_irqs)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    APBState *d;
-    PCIDevice *pci_dev;
-    PCIBridge *br;
-
-    /* Ultrasparc PBM main bus */
-    dev = qdev_create(NULL, "pbm");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    /* apb_config */
-    sysbus_mmio_map(s, 0, special_base);
-    /* PCI configuration space */
-    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
-    /* pci_ioport */
-    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
-    d = FROM_SYSBUS(APBState, s);
-
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
-
-    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
-                              pci_apb_set_irq, pci_pbm_map_irq, d,
-                              &d->pci_mmio,
-                              get_system_io(),
-                              0, 32, TYPE_PCI_BUS);
-
-    *pbm_irqs = d->pbm_irqs;
-    d->ivec_irqs = ivec_irqs;
-
-    pci_create_simple(d->bus, 0, "pbm-pci");
-
-    /* APB secondary busses */
-    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
-                                   "pbm-bridge");
-    br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
-                       pci_apb_map_irq);
-    qdev_init_nofail(&pci_dev->qdev);
-    *bus2 = pci_bridge_get_sec_bus(br);
-
-    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
-                                   "pbm-bridge");
-    br = DO_UPCAST(PCIBridge, dev, pci_dev);
-    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
-                       pci_apb_map_irq);
-    qdev_init_nofail(&pci_dev->qdev);
-    *bus3 = pci_bridge_get_sec_bus(br);
-
-    return d->bus;
-}
-
-static void pci_pbm_reset(DeviceState *d)
-{
-    unsigned int i;
-    APBState *s = container_of(d, APBState, busdev.qdev);
-
-    for (i = 0; i < 8; i++) {
-        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
-    }
-    for (i = 0; i < 32; i++) {
-        s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
-    }
-
-    if (s->nr_resets++ == 0) {
-        /* Power on reset */
-        s->reset_control = POR;
-    }
-}
-
-static const MemoryRegionOps pci_config_ops = {
-    .read = apb_pci_config_read,
-    .write = apb_pci_config_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pci_pbm_init_device(SysBusDevice *dev)
-{
-    APBState *s;
-    unsigned int i;
-
-    s = FROM_SYSBUS(APBState, dev);
-    for (i = 0; i < 8; i++) {
-        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
-    }
-    for (i = 0; i < 32; i++) {
-        s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
-    }
-    s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
-
-    /* apb_config */
-    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
-                          0x10000);
-    /* at region 0 */
-    sysbus_init_mmio(dev, &s->apb_config);
-
-    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
-                          0x1000000);
-    /* at region 1 */
-    sysbus_init_mmio(dev, &s->pci_config);
-
-    /* pci_ioport */
-    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
-                          "apb-pci-ioport", 0x10000);
-    /* at region 2 */
-    sysbus_init_mmio(dev, &s->pci_ioport);
-
-    return 0;
-}
-
-static int pbm_pci_host_init(PCIDevice *d)
-{
-    pci_set_word(d->config + PCI_COMMAND,
-                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-    pci_set_word(d->config + PCI_STATUS,
-                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
-                 PCI_STATUS_DEVSEL_MEDIUM);
-    return 0;
-}
-
-static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = pbm_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_SUN;
-    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo pbm_pci_host_info = {
-    .name          = "pbm-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = pbm_pci_host_class_init,
-};
-
-static void pbm_host_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pci_pbm_init_device;
-    dc->reset = pci_pbm_reset;
-}
-
-static const TypeInfo pbm_host_info = {
-    .name          = "pbm",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(APBState),
-    .class_init    = pbm_host_class_init,
-};
-
-static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = apb_pci_bridge_initfn;
-    k->exit = pci_bridge_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_SUN;
-    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
-    k->revision = 0x11;
-    k->config_write = pci_bridge_write_config;
-    k->is_bridge = 1;
-    dc->reset = pci_bridge_reset;
-    dc->vmsd = &vmstate_pci_device;
-}
-
-static const TypeInfo pbm_pci_bridge_info = {
-    .name          = "pbm-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIBridge),
-    .class_init    = pbm_pci_bridge_class_init,
-};
-
-static void pbm_register_types(void)
-{
-    type_register_static(&pbm_host_info);
-    type_register_static(&pbm_pci_host_info);
-    type_register_static(&pbm_pci_bridge_info);
-}
-
-type_init(pbm_register_types)
diff --git a/hw/bonito.c b/hw/bonito.c
deleted file mode 100644 (file)
index 974150b..0000000
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- * bonito north bridge support
- *
- * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
- * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-/*
- * fulong 2e mini pc has a bonito north bridge.
- */
-
-/* what is the meaning of devfn in qemu and IDSEL in bonito northbridge?
- *
- * devfn   pci_slot<<3  + funno
- * one pci bus can have 32 devices and each device can have 8 functions.
- *
- * In bonito north bridge, pci slot = IDSEL bit - 12.
- * For example, PCI_IDSEL_VIA686B = 17,
- * pci slot = 17-12=5
- *
- * so
- * VT686B_FUN0's devfn = (5<<3)+0
- * VT686B_FUN1's devfn = (5<<3)+1
- *
- * qemu also uses pci address for north bridge to access pci config register.
- * bus_no   [23:16]
- * dev_no   [15:11]
- * fun_no   [10:8]
- * reg_no   [7:2]
- *
- * so function bonito_sbridge_pciaddr for the translation from
- * north bridge address to pci address.
- */
-
-#include <assert.h>
-
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/i386/pc.h"
-#include "hw/mips/mips.h"
-#include "hw/pci/pci_host.h"
-#include "sysemu/sysemu.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_BONITO
-
-#ifdef DEBUG_BONITO
-#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-/* from linux soure code. include/asm-mips/mips-boards/bonito64.h*/
-#define BONITO_BOOT_BASE        0x1fc00000
-#define BONITO_BOOT_SIZE        0x00100000
-#define BONITO_BOOT_TOP         (BONITO_BOOT_BASE+BONITO_BOOT_SIZE-1)
-#define BONITO_FLASH_BASE       0x1c000000
-#define BONITO_FLASH_SIZE       0x03000000
-#define BONITO_FLASH_TOP        (BONITO_FLASH_BASE+BONITO_FLASH_SIZE-1)
-#define BONITO_SOCKET_BASE      0x1f800000
-#define BONITO_SOCKET_SIZE      0x00400000
-#define BONITO_SOCKET_TOP       (BONITO_SOCKET_BASE+BONITO_SOCKET_SIZE-1)
-#define BONITO_REG_BASE         0x1fe00000
-#define BONITO_REG_SIZE         0x00040000
-#define BONITO_REG_TOP          (BONITO_REG_BASE+BONITO_REG_SIZE-1)
-#define BONITO_DEV_BASE         0x1ff00000
-#define BONITO_DEV_SIZE         0x00100000
-#define BONITO_DEV_TOP          (BONITO_DEV_BASE+BONITO_DEV_SIZE-1)
-#define BONITO_PCILO_BASE       0x10000000
-#define BONITO_PCILO_BASE_VA    0xb0000000
-#define BONITO_PCILO_SIZE       0x0c000000
-#define BONITO_PCILO_TOP        (BONITO_PCILO_BASE+BONITO_PCILO_SIZE-1)
-#define BONITO_PCILO0_BASE      0x10000000
-#define BONITO_PCILO1_BASE      0x14000000
-#define BONITO_PCILO2_BASE      0x18000000
-#define BONITO_PCIHI_BASE       0x20000000
-#define BONITO_PCIHI_SIZE       0x20000000
-#define BONITO_PCIHI_TOP        (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1)
-#define BONITO_PCIIO_BASE       0x1fd00000
-#define BONITO_PCIIO_BASE_VA    0xbfd00000
-#define BONITO_PCIIO_SIZE       0x00010000
-#define BONITO_PCIIO_TOP        (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1)
-#define BONITO_PCICFG_BASE      0x1fe80000
-#define BONITO_PCICFG_SIZE      0x00080000
-#define BONITO_PCICFG_TOP       (BONITO_PCICFG_BASE+BONITO_PCICFG_SIZE-1)
-
-
-#define BONITO_PCICONFIGBASE    0x00
-#define BONITO_REGBASE          0x100
-
-#define BONITO_PCICONFIG_BASE   (BONITO_PCICONFIGBASE+BONITO_REG_BASE)
-#define BONITO_PCICONFIG_SIZE   (0x100)
-
-#define BONITO_INTERNAL_REG_BASE  (BONITO_REGBASE+BONITO_REG_BASE)
-#define BONITO_INTERNAL_REG_SIZE  (0x70)
-
-#define BONITO_SPCICONFIG_BASE  (BONITO_PCICFG_BASE)
-#define BONITO_SPCICONFIG_SIZE  (BONITO_PCICFG_SIZE)
-
-
-
-/* 1. Bonito h/w Configuration */
-/* Power on register */
-
-#define BONITO_BONPONCFG        (0x00 >> 2)      /* 0x100 */
-#define BONITO_BONGENCFG_OFFSET 0x4
-#define BONITO_BONGENCFG        (BONITO_BONGENCFG_OFFSET>>2)   /*0x104 */
-
-/* 2. IO & IDE configuration */
-#define BONITO_IODEVCFG         (0x08 >> 2)      /* 0x108 */
-
-/* 3. IO & IDE configuration */
-#define BONITO_SDCFG            (0x0c >> 2)      /* 0x10c */
-
-/* 4. PCI address map control */
-#define BONITO_PCIMAP           (0x10 >> 2)      /* 0x110 */
-#define BONITO_PCIMEMBASECFG    (0x14 >> 2)      /* 0x114 */
-#define BONITO_PCIMAP_CFG       (0x18 >> 2)      /* 0x118 */
-
-/* 5. ICU & GPIO regs */
-/* GPIO Regs - r/w */
-#define BONITO_GPIODATA_OFFSET  0x1c
-#define BONITO_GPIODATA         (BONITO_GPIODATA_OFFSET >> 2)   /* 0x11c */
-#define BONITO_GPIOIE           (0x20 >> 2)      /* 0x120 */
-
-/* ICU Configuration Regs - r/w */
-#define BONITO_INTEDGE          (0x24 >> 2)      /* 0x124 */
-#define BONITO_INTSTEER         (0x28 >> 2)      /* 0x128 */
-#define BONITO_INTPOL           (0x2c >> 2)      /* 0x12c */
-
-/* ICU Enable Regs - IntEn & IntISR are r/o. */
-#define BONITO_INTENSET         (0x30 >> 2)      /* 0x130 */
-#define BONITO_INTENCLR         (0x34 >> 2)      /* 0x134 */
-#define BONITO_INTEN            (0x38 >> 2)      /* 0x138 */
-#define BONITO_INTISR           (0x3c >> 2)      /* 0x13c */
-
-/* PCI mail boxes */
-#define BONITO_PCIMAIL0_OFFSET    0x40
-#define BONITO_PCIMAIL1_OFFSET    0x44
-#define BONITO_PCIMAIL2_OFFSET    0x48
-#define BONITO_PCIMAIL3_OFFSET    0x4c
-#define BONITO_PCIMAIL0         (0x40 >> 2)      /* 0x140 */
-#define BONITO_PCIMAIL1         (0x44 >> 2)      /* 0x144 */
-#define BONITO_PCIMAIL2         (0x48 >> 2)      /* 0x148 */
-#define BONITO_PCIMAIL3         (0x4c >> 2)      /* 0x14c */
-
-/* 6. PCI cache */
-#define BONITO_PCICACHECTRL     (0x50 >> 2)      /* 0x150 */
-#define BONITO_PCICACHETAG      (0x54 >> 2)      /* 0x154 */
-#define BONITO_PCIBADADDR       (0x58 >> 2)      /* 0x158 */
-#define BONITO_PCIMSTAT         (0x5c >> 2)      /* 0x15c */
-
-/* 7. other*/
-#define BONITO_TIMECFG          (0x60 >> 2)      /* 0x160 */
-#define BONITO_CPUCFG           (0x64 >> 2)      /* 0x164 */
-#define BONITO_DQCFG            (0x68 >> 2)      /* 0x168 */
-#define BONITO_MEMSIZE          (0x6C >> 2)      /* 0x16c */
-
-#define BONITO_REGS             (0x70 >> 2)
-
-/* PCI config for south bridge. type 0 */
-#define BONITO_PCICONF_IDSEL_MASK      0xfffff800     /* [31:11] */
-#define BONITO_PCICONF_IDSEL_OFFSET    11
-#define BONITO_PCICONF_FUN_MASK        0x700    /* [10:8] */
-#define BONITO_PCICONF_FUN_OFFSET      8
-#define BONITO_PCICONF_REG_MASK        0xFC
-#define BONITO_PCICONF_REG_OFFSET      0
-
-
-/* idsel BIT = pci slot number +12 */
-#define PCI_SLOT_BASE              12
-#define PCI_IDSEL_VIA686B_BIT      (17)
-#define PCI_IDSEL_VIA686B          (1<<PCI_IDSEL_VIA686B_BIT)
-
-#define PCI_ADDR(busno,devno,funno,regno)  \
-    ((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno))
-
-#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
-
-typedef struct BonitoState BonitoState;
-
-typedef struct PCIBonitoState
-{
-    PCIDevice dev;
-
-    BonitoState *pcihost;
-    uint32_t regs[BONITO_REGS];
-
-    struct bonldma {
-        uint32_t ldmactrl;
-        uint32_t ldmastat;
-        uint32_t ldmaaddr;
-        uint32_t ldmago;
-    } bonldma;
-
-    /* Based at 1fe00300, bonito Copier */
-    struct boncop {
-        uint32_t copctrl;
-        uint32_t copstat;
-        uint32_t coppaddr;
-        uint32_t copgo;
-    } boncop;
-
-    /* Bonito registers */
-    MemoryRegion iomem;
-    MemoryRegion iomem_ldma;
-    MemoryRegion iomem_cop;
-
-    hwaddr bonito_pciio_start;
-    hwaddr bonito_pciio_length;
-    int bonito_pciio_handle;
-
-    hwaddr bonito_localio_start;
-    hwaddr bonito_localio_length;
-    int bonito_localio_handle;
-
-} PCIBonitoState;
-
-#define BONITO_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE)
-
-struct BonitoState {
-    PCIHostState parent_obj;
-
-    qemu_irq *pic;
-
-    PCIBonitoState *pci_dev;
-};
-
-static void bonito_writel(void *opaque, hwaddr addr,
-                          uint64_t val, unsigned size)
-{
-    PCIBonitoState *s = opaque;
-    uint32_t saddr;
-    int reset = 0;
-
-    saddr = (addr - BONITO_REGBASE) >> 2;
-
-    DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", addr, val, saddr);
-    switch (saddr) {
-    case BONITO_BONPONCFG:
-    case BONITO_IODEVCFG:
-    case BONITO_SDCFG:
-    case BONITO_PCIMAP:
-    case BONITO_PCIMEMBASECFG:
-    case BONITO_PCIMAP_CFG:
-    case BONITO_GPIODATA:
-    case BONITO_GPIOIE:
-    case BONITO_INTEDGE:
-    case BONITO_INTSTEER:
-    case BONITO_INTPOL:
-    case BONITO_PCIMAIL0:
-    case BONITO_PCIMAIL1:
-    case BONITO_PCIMAIL2:
-    case BONITO_PCIMAIL3:
-    case BONITO_PCICACHECTRL:
-    case BONITO_PCICACHETAG:
-    case BONITO_PCIBADADDR:
-    case BONITO_PCIMSTAT:
-    case BONITO_TIMECFG:
-    case BONITO_CPUCFG:
-    case BONITO_DQCFG:
-    case BONITO_MEMSIZE:
-        s->regs[saddr] = val;
-        break;
-    case BONITO_BONGENCFG:
-        if (!(s->regs[saddr] & 0x04) && (val & 0x04)) {
-            reset = 1; /* bit 2 jump from 0 to 1 cause reset */
-        }
-        s->regs[saddr] = val;
-        if (reset) {
-            qemu_system_reset_request();
-        }
-        break;
-    case BONITO_INTENSET:
-        s->regs[BONITO_INTENSET] = val;
-        s->regs[BONITO_INTEN] |= val;
-        break;
-    case BONITO_INTENCLR:
-        s->regs[BONITO_INTENCLR] = val;
-        s->regs[BONITO_INTEN] &= ~val;
-        break;
-    case BONITO_INTEN:
-    case BONITO_INTISR:
-        DPRINTF("write to readonly bonito register %x\n", saddr);
-        break;
-    default:
-        DPRINTF("write to unknown bonito register %x\n", saddr);
-        break;
-    }
-}
-
-static uint64_t bonito_readl(void *opaque, hwaddr addr,
-                             unsigned size)
-{
-    PCIBonitoState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - BONITO_REGBASE) >> 2;
-
-    DPRINTF("bonito_readl "TARGET_FMT_plx"\n", addr);
-    switch (saddr) {
-    case BONITO_INTISR:
-        return s->regs[saddr];
-    default:
-        return s->regs[saddr];
-    }
-}
-
-static const MemoryRegionOps bonito_ops = {
-    .read = bonito_readl,
-    .write = bonito_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static void bonito_pciconf_writel(void *opaque, hwaddr addr,
-                                  uint64_t val, unsigned size)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-
-    DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
-    d->config_write(d, addr, val, 4);
-}
-
-static uint64_t bonito_pciconf_readl(void *opaque, hwaddr addr,
-                                     unsigned size)
-{
-
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-
-    DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr);
-    return d->config_read(d, addr, 4);
-}
-
-/* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
-
-static const MemoryRegionOps bonito_pciconf_ops = {
-    .read = bonito_pciconf_readl,
-    .write = bonito_pciconf_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static uint64_t bonito_ldma_readl(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    uint32_t val;
-    PCIBonitoState *s = opaque;
-
-    val = ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)];
-
-    return val;
-}
-
-static void bonito_ldma_writel(void *opaque, hwaddr addr,
-                               uint64_t val, unsigned size)
-{
-    PCIBonitoState *s = opaque;
-
-    ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff;
-}
-
-static const MemoryRegionOps bonito_ldma_ops = {
-    .read = bonito_ldma_readl,
-    .write = bonito_ldma_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static uint64_t bonito_cop_readl(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    uint32_t val;
-    PCIBonitoState *s = opaque;
-
-    val = ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)];
-
-    return val;
-}
-
-static void bonito_cop_writel(void *opaque, hwaddr addr,
-                              uint64_t val, unsigned size)
-{
-    PCIBonitoState *s = opaque;
-
-    ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff;
-}
-
-static const MemoryRegionOps bonito_cop_ops = {
-    .read = bonito_cop_readl,
-    .write = bonito_cop_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr)
-{
-    PCIBonitoState *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t cfgaddr;
-    uint32_t idsel;
-    uint32_t devno;
-    uint32_t funno;
-    uint32_t regno;
-    uint32_t pciaddr;
-
-    /* support type0 pci config */
-    if ((s->regs[BONITO_PCIMAP_CFG] & 0x10000) != 0x0) {
-        return 0xffffffff;
-    }
-
-    cfgaddr = addr & 0xffff;
-    cfgaddr |= (s->regs[BONITO_PCIMAP_CFG] & 0xffff) << 16;
-
-    idsel = (cfgaddr & BONITO_PCICONF_IDSEL_MASK) >> BONITO_PCICONF_IDSEL_OFFSET;
-    devno = ffs(idsel) - 1;
-    funno = (cfgaddr & BONITO_PCICONF_FUN_MASK) >> BONITO_PCICONF_FUN_OFFSET;
-    regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET;
-
-    if (idsel == 0) {
-        fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx
-            ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]);
-        exit(1);
-    }
-    pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno);
-    DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n",
-        cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno);
-
-    return pciaddr;
-}
-
-static void bonito_spciconf_writeb(void *opaque, hwaddr addr,
-                                   uint32_t val)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_writeb "TARGET_FMT_plx" val %x\n", addr, val);
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-}
-
-static void bonito_spciconf_writew(void *opaque, hwaddr addr,
-                                   uint32_t val)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);
-    assert((addr & 0x1) == 0);
-
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(phb->bus, phb->config_reg, val, 2);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-}
-
-static void bonito_spciconf_writel(void *opaque, hwaddr addr,
-                                   uint32_t val)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
-    assert((addr & 0x3) == 0);
-
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-    pci_data_write(phb->bus, phb->config_reg, val, 4);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-}
-
-static uint32_t bonito_spciconf_readb(void *opaque, hwaddr addr)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"\n", addr);
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return 0xff;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-
-    return pci_data_read(phb->bus, phb->config_reg, 1);
-}
-
-static uint32_t bonito_spciconf_readw(void *opaque, hwaddr addr)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr);
-    assert((addr & 0x1) == 0);
-
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return 0xffff;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-
-    return pci_data_read(phb->bus, phb->config_reg, 2);
-}
-
-static uint32_t bonito_spciconf_readl(void *opaque, hwaddr addr)
-{
-    PCIBonitoState *s = opaque;
-    PCIDevice *d = PCI_DEVICE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-    uint32_t pciaddr;
-    uint16_t status;
-
-    DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr);
-    assert((addr & 0x3) == 0);
-
-    pciaddr = bonito_sbridge_pciaddr(s, addr);
-
-    if (pciaddr == 0xffffffff) {
-        return 0xffffffff;
-    }
-
-    /* set the pci address in s->config_reg */
-    phb->config_reg = (pciaddr) | (1u << 31);
-
-    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
-    status = pci_get_word(d->config + PCI_STATUS);
-    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
-    pci_set_word(d->config + PCI_STATUS, status);
-
-    return pci_data_read(phb->bus, phb->config_reg, 4);
-}
-
-/* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
-static const MemoryRegionOps bonito_spciconf_ops = {
-    .old_mmio = {
-        .read = {
-            bonito_spciconf_readb,
-            bonito_spciconf_readw,
-            bonito_spciconf_readl,
-        },
-        .write = {
-            bonito_spciconf_writeb,
-            bonito_spciconf_writew,
-            bonito_spciconf_writel,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-#define BONITO_IRQ_BASE 32
-
-static void pci_bonito_set_irq(void *opaque, int irq_num, int level)
-{
-    BonitoState *s = opaque;
-    qemu_irq *pic = s->pic;
-    PCIBonitoState *bonito_state = s->pci_dev;
-    int internal_irq = irq_num - BONITO_IRQ_BASE;
-
-    if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) {
-        qemu_irq_pulse(*pic);
-    } else {   /* level triggered */
-        if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) {
-            qemu_irq_raise(*pic);
-        } else {
-            qemu_irq_lower(*pic);
-        }
-    }
-}
-
-/* map the original irq (0~3) to bonito irq (16~47, but 16~31 are unused) */
-static int pci_bonito_map_irq(PCIDevice * pci_dev, int irq_num)
-{
-    int slot;
-
-    slot = (pci_dev->devfn >> 3);
-
-    switch (slot) {
-    case 5:   /* FULONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */
-        return irq_num % 4 + BONITO_IRQ_BASE;
-    case 6:   /* FULONG2E_ATI_SLOT, VGA */
-        return 4 + BONITO_IRQ_BASE;
-    case 7:   /* FULONG2E_RTL_SLOT, RTL8139 */
-        return 5 + BONITO_IRQ_BASE;
-    case 8 ... 12: /* PCI slot 1 to 4 */
-        return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE;
-    default:  /* Unknown device, don't do any translation */
-        return irq_num;
-    }
-}
-
-static void bonito_reset(void *opaque)
-{
-    PCIBonitoState *s = opaque;
-
-    /* set the default value of north bridge registers */
-
-    s->regs[BONITO_BONPONCFG] = 0xc40;
-    s->regs[BONITO_BONGENCFG] = 0x1384;
-    s->regs[BONITO_IODEVCFG] = 0x2bff8010;
-    s->regs[BONITO_SDCFG] = 0x255e0091;
-
-    s->regs[BONITO_GPIODATA] = 0x1ff;
-    s->regs[BONITO_GPIOIE] = 0x1ff;
-    s->regs[BONITO_DQCFG] = 0x8;
-    s->regs[BONITO_MEMSIZE] = 0x10000000;
-    s->regs[BONITO_PCIMAP] = 0x6140;
-}
-
-static const VMStateDescription vmstate_bonito = {
-    .name = "Bonito",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PCIBonitoState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int bonito_pcihost_initfn(SysBusDevice *dev)
-{
-    PCIHostState *phb = PCI_HOST_BRIDGE(dev);
-
-    phb->bus = pci_register_bus(DEVICE(dev), "pci",
-                                pci_bonito_set_irq, pci_bonito_map_irq, dev,
-                                get_system_memory(), get_system_io(),
-                                0x28, 32, TYPE_PCI_BUS);
-
-    return 0;
-}
-
-static int bonito_initfn(PCIDevice *dev)
-{
-    PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
-    SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
-
-    /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
-    pci_config_set_prog_interface(dev->config, 0x00);
-
-    /* set the north bridge register mapping */
-    memory_region_init_io(&s->iomem, &bonito_ops, s,
-                          "north-bridge-register", BONITO_INTERNAL_REG_SIZE);
-    sysbus_init_mmio(sysbus, &s->iomem);
-    sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
-
-    /* set the north bridge pci configure  mapping */
-    memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s,
-                          "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
-    sysbus_init_mmio(sysbus, &phb->conf_mem);
-    sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
-
-    /* set the south bridge pci configure  mapping */
-    memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s,
-                          "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
-    sysbus_init_mmio(sysbus, &phb->data_mem);
-    sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
-
-    memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
-                          "ldma", 0x100);
-    sysbus_init_mmio(sysbus, &s->iomem_ldma);
-    sysbus_mmio_map(sysbus, 3, 0xbfe00200);
-
-    memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s,
-                          "cop", 0x100);
-    sysbus_init_mmio(sysbus, &s->iomem_cop);
-    sysbus_mmio_map(sysbus, 4, 0xbfe00300);
-
-    /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
-    s->bonito_pciio_start = BONITO_PCIIO_BASE;
-    s->bonito_pciio_length = BONITO_PCIIO_SIZE;
-    isa_mem_base = s->bonito_pciio_start;
-    isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length);
-
-    /* add pci local io mapping */
-    s->bonito_localio_start = BONITO_DEV_BASE;
-    s->bonito_localio_length = BONITO_DEV_SIZE;
-    isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length);
-
-    /* set the default value of north bridge pci config */
-    pci_set_word(dev->config + PCI_COMMAND, 0x0000);
-    pci_set_word(dev->config + PCI_STATUS, 0x0000);
-    pci_set_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID, 0x0000);
-    pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x0000);
-
-    pci_set_byte(dev->config + PCI_INTERRUPT_LINE, 0x00);
-    pci_set_byte(dev->config + PCI_INTERRUPT_PIN, 0x01);
-    pci_set_byte(dev->config + PCI_MIN_GNT, 0x3c);
-    pci_set_byte(dev->config + PCI_MAX_LAT, 0x00);
-
-    qemu_register_reset(bonito_reset, s);
-
-    return 0;
-}
-
-PCIBus *bonito_init(qemu_irq *pic)
-{
-    DeviceState *dev;
-    BonitoState *pcihost;
-    PCIHostState *phb;
-    PCIBonitoState *s;
-    PCIDevice *d;
-
-    dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE);
-    phb = PCI_HOST_BRIDGE(dev);
-    pcihost = BONITO_PCI_HOST_BRIDGE(dev);
-    pcihost->pic = pic;
-    qdev_init_nofail(dev);
-
-    /* set the pcihost pointer before bonito_initfn is called */
-    d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito");
-    s = DO_UPCAST(PCIBonitoState, dev, d);
-    s->pcihost = pcihost;
-    pcihost->pci_dev = s;
-    qdev_init_nofail(DEVICE(d));
-
-    return phb->bus;
-}
-
-static void bonito_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = bonito_initfn;
-    k->vendor_id = 0xdf53;
-    k->device_id = 0x00d5;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-    dc->desc = "Host bridge";
-    dc->no_user = 1;
-    dc->vmsd = &vmstate_bonito;
-}
-
-static const TypeInfo bonito_info = {
-    .name          = "Bonito",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIBonitoState),
-    .class_init    = bonito_class_init,
-};
-
-static void bonito_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = bonito_pcihost_initfn;
-    dc->no_user = 1;
-}
-
-static const TypeInfo bonito_pcihost_info = {
-    .name          = TYPE_BONITO_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(BonitoState),
-    .class_init    = bonito_pcihost_class_init,
-};
-
-static void bonito_register_types(void)
-{
-    type_register_static(&bonito_pcihost_info);
-    type_register_static(&bonito_info);
-}
-
-type_init(bonito_register_types)
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
deleted file mode 100644 (file)
index 189e865..0000000
+++ /dev/null
@@ -1,1188 +0,0 @@
-/*
- * QEMU GT64120 PCI host
- *
- * Copyright (c) 2006,2007 Aurelien Jarno
- *
- * 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/hw.h"
-#include "hw/mips/mips.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "hw/i386/pc.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG
-
-#ifdef DEBUG
-#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-#define GT_REGS                        (0x1000 >> 2)
-
-/* CPU Configuration */
-#define GT_CPU                 (0x000 >> 2)
-#define GT_MULTI               (0x120 >> 2)
-
-/* CPU Address Decode */
-#define GT_SCS10LD             (0x008 >> 2)
-#define GT_SCS10HD             (0x010 >> 2)
-#define GT_SCS32LD             (0x018 >> 2)
-#define GT_SCS32HD             (0x020 >> 2)
-#define GT_CS20LD              (0x028 >> 2)
-#define GT_CS20HD              (0x030 >> 2)
-#define GT_CS3BOOTLD           (0x038 >> 2)
-#define GT_CS3BOOTHD           (0x040 >> 2)
-#define GT_PCI0IOLD                    (0x048 >> 2)
-#define GT_PCI0IOHD                    (0x050 >> 2)
-#define GT_PCI0M0LD                    (0x058 >> 2)
-#define GT_PCI0M0HD                    (0x060 >> 2)
-#define GT_PCI0M1LD                    (0x080 >> 2)
-#define GT_PCI0M1HD                    (0x088 >> 2)
-#define GT_PCI1IOLD                    (0x090 >> 2)
-#define GT_PCI1IOHD                    (0x098 >> 2)
-#define GT_PCI1M0LD                    (0x0a0 >> 2)
-#define GT_PCI1M0HD                    (0x0a8 >> 2)
-#define GT_PCI1M1LD                    (0x0b0 >> 2)
-#define GT_PCI1M1HD                    (0x0b8 >> 2)
-#define GT_ISD                 (0x068 >> 2)
-
-#define GT_SCS10AR             (0x0d0 >> 2)
-#define GT_SCS32AR             (0x0d8 >> 2)
-#define GT_CS20R               (0x0e0 >> 2)
-#define GT_CS3BOOTR                    (0x0e8 >> 2)
-
-#define GT_PCI0IOREMAP         (0x0f0 >> 2)
-#define GT_PCI0M0REMAP         (0x0f8 >> 2)
-#define GT_PCI0M1REMAP         (0x100 >> 2)
-#define GT_PCI1IOREMAP         (0x108 >> 2)
-#define GT_PCI1M0REMAP         (0x110 >> 2)
-#define GT_PCI1M1REMAP         (0x118 >> 2)
-
-/* CPU Error Report */
-#define GT_CPUERR_ADDRLO       (0x070 >> 2)
-#define GT_CPUERR_ADDRHI       (0x078 >> 2)
-#define GT_CPUERR_DATALO       (0x128 >> 2)            /* GT-64120A only  */
-#define GT_CPUERR_DATAHI       (0x130 >> 2)            /* GT-64120A only  */
-#define GT_CPUERR_PARITY       (0x138 >> 2)            /* GT-64120A only  */
-
-/* CPU Sync Barrier */
-#define GT_PCI0SYNC                    (0x0c0 >> 2)
-#define GT_PCI1SYNC                    (0x0c8 >> 2)
-
-/* SDRAM and Device Address Decode */
-#define GT_SCS0LD              (0x400 >> 2)
-#define GT_SCS0HD              (0x404 >> 2)
-#define GT_SCS1LD              (0x408 >> 2)
-#define GT_SCS1HD              (0x40c >> 2)
-#define GT_SCS2LD              (0x410 >> 2)
-#define GT_SCS2HD              (0x414 >> 2)
-#define GT_SCS3LD              (0x418 >> 2)
-#define GT_SCS3HD              (0x41c >> 2)
-#define GT_CS0LD               (0x420 >> 2)
-#define GT_CS0HD               (0x424 >> 2)
-#define GT_CS1LD               (0x428 >> 2)
-#define GT_CS1HD               (0x42c >> 2)
-#define GT_CS2LD               (0x430 >> 2)
-#define GT_CS2HD               (0x434 >> 2)
-#define GT_CS3LD               (0x438 >> 2)
-#define GT_CS3HD               (0x43c >> 2)
-#define GT_BOOTLD              (0x440 >> 2)
-#define GT_BOOTHD              (0x444 >> 2)
-#define GT_ADERR               (0x470 >> 2)
-
-/* SDRAM Configuration */
-#define GT_SDRAM_CFG           (0x448 >> 2)
-#define GT_SDRAM_OPMODE        (0x474 >> 2)
-#define GT_SDRAM_BM                    (0x478 >> 2)
-#define GT_SDRAM_ADDRDECODE            (0x47c >> 2)
-
-/* SDRAM Parameters */
-#define GT_SDRAM_B0                    (0x44c >> 2)
-#define GT_SDRAM_B1                    (0x450 >> 2)
-#define GT_SDRAM_B2                    (0x454 >> 2)
-#define GT_SDRAM_B3                    (0x458 >> 2)
-
-/* Device Parameters */
-#define GT_DEV_B0              (0x45c >> 2)
-#define GT_DEV_B1              (0x460 >> 2)
-#define GT_DEV_B2              (0x464 >> 2)
-#define GT_DEV_B3              (0x468 >> 2)
-#define GT_DEV_BOOT                    (0x46c >> 2)
-
-/* ECC */
-#define GT_ECC_ERRDATALO       (0x480 >> 2)            /* GT-64120A only  */
-#define GT_ECC_ERRDATAHI       (0x484 >> 2)            /* GT-64120A only  */
-#define GT_ECC_MEM             (0x488 >> 2)            /* GT-64120A only  */
-#define GT_ECC_CALC            (0x48c >> 2)            /* GT-64120A only  */
-#define GT_ECC_ERRADDR         (0x490 >> 2)            /* GT-64120A only  */
-
-/* DMA Record */
-#define GT_DMA0_CNT                    (0x800 >> 2)
-#define GT_DMA1_CNT                    (0x804 >> 2)
-#define GT_DMA2_CNT                    (0x808 >> 2)
-#define GT_DMA3_CNT                    (0x80c >> 2)
-#define GT_DMA0_SA             (0x810 >> 2)
-#define GT_DMA1_SA             (0x814 >> 2)
-#define GT_DMA2_SA             (0x818 >> 2)
-#define GT_DMA3_SA             (0x81c >> 2)
-#define GT_DMA0_DA             (0x820 >> 2)
-#define GT_DMA1_DA             (0x824 >> 2)
-#define GT_DMA2_DA             (0x828 >> 2)
-#define GT_DMA3_DA             (0x82c >> 2)
-#define GT_DMA0_NEXT           (0x830 >> 2)
-#define GT_DMA1_NEXT           (0x834 >> 2)
-#define GT_DMA2_NEXT           (0x838 >> 2)
-#define GT_DMA3_NEXT           (0x83c >> 2)
-#define GT_DMA0_CUR                    (0x870 >> 2)
-#define GT_DMA1_CUR                    (0x874 >> 2)
-#define GT_DMA2_CUR                    (0x878 >> 2)
-#define GT_DMA3_CUR                    (0x87c >> 2)
-
-/* DMA Channel Control */
-#define GT_DMA0_CTRL           (0x840 >> 2)
-#define GT_DMA1_CTRL           (0x844 >> 2)
-#define GT_DMA2_CTRL           (0x848 >> 2)
-#define GT_DMA3_CTRL           (0x84c >> 2)
-
-/* DMA Arbiter */
-#define GT_DMA_ARB             (0x860 >> 2)
-
-/* Timer/Counter */
-#define GT_TC0                 (0x850 >> 2)
-#define GT_TC1                 (0x854 >> 2)
-#define GT_TC2                 (0x858 >> 2)
-#define GT_TC3                 (0x85c >> 2)
-#define GT_TC_CONTROL          (0x864 >> 2)
-
-/* PCI Internal */
-#define GT_PCI0_CMD                    (0xc00 >> 2)
-#define GT_PCI0_TOR                    (0xc04 >> 2)
-#define GT_PCI0_BS_SCS10       (0xc08 >> 2)
-#define GT_PCI0_BS_SCS32       (0xc0c >> 2)
-#define GT_PCI0_BS_CS20        (0xc10 >> 2)
-#define GT_PCI0_BS_CS3BT       (0xc14 >> 2)
-#define GT_PCI1_IACK           (0xc30 >> 2)
-#define GT_PCI0_IACK           (0xc34 >> 2)
-#define GT_PCI0_BARE           (0xc3c >> 2)
-#define GT_PCI0_PREFMBR        (0xc40 >> 2)
-#define GT_PCI0_SCS10_BAR      (0xc48 >> 2)
-#define GT_PCI0_SCS32_BAR      (0xc4c >> 2)
-#define GT_PCI0_CS20_BAR       (0xc50 >> 2)
-#define GT_PCI0_CS3BT_BAR      (0xc54 >> 2)
-#define GT_PCI0_SSCS10_BAR     (0xc58 >> 2)
-#define GT_PCI0_SSCS32_BAR     (0xc5c >> 2)
-#define GT_PCI0_SCS3BT_BAR     (0xc64 >> 2)
-#define GT_PCI1_CMD                    (0xc80 >> 2)
-#define GT_PCI1_TOR                    (0xc84 >> 2)
-#define GT_PCI1_BS_SCS10       (0xc88 >> 2)
-#define GT_PCI1_BS_SCS32       (0xc8c >> 2)
-#define GT_PCI1_BS_CS20        (0xc90 >> 2)
-#define GT_PCI1_BS_CS3BT       (0xc94 >> 2)
-#define GT_PCI1_BARE           (0xcbc >> 2)
-#define GT_PCI1_PREFMBR        (0xcc0 >> 2)
-#define GT_PCI1_SCS10_BAR      (0xcc8 >> 2)
-#define GT_PCI1_SCS32_BAR      (0xccc >> 2)
-#define GT_PCI1_CS20_BAR       (0xcd0 >> 2)
-#define GT_PCI1_CS3BT_BAR      (0xcd4 >> 2)
-#define GT_PCI1_SSCS10_BAR     (0xcd8 >> 2)
-#define GT_PCI1_SSCS32_BAR     (0xcdc >> 2)
-#define GT_PCI1_SCS3BT_BAR     (0xce4 >> 2)
-#define GT_PCI1_CFGADDR        (0xcf0 >> 2)
-#define GT_PCI1_CFGDATA        (0xcf4 >> 2)
-#define GT_PCI0_CFGADDR        (0xcf8 >> 2)
-#define GT_PCI0_CFGDATA        (0xcfc >> 2)
-
-/* Interrupts */
-#define GT_INTRCAUSE           (0xc18 >> 2)
-#define GT_INTRMASK                    (0xc1c >> 2)
-#define GT_PCI0_ICMASK         (0xc24 >> 2)
-#define GT_PCI0_SERR0MASK      (0xc28 >> 2)
-#define GT_CPU_INTSEL          (0xc70 >> 2)
-#define GT_PCI0_INTSEL         (0xc74 >> 2)
-#define GT_HINTRCAUSE          (0xc98 >> 2)
-#define GT_HINTRMASK           (0xc9c >> 2)
-#define GT_PCI0_HICMASK        (0xca4 >> 2)
-#define GT_PCI1_SERR1MASK      (0xca8 >> 2)
-
-#define PCI_MAPPING_ENTRY(regname)            \
-    hwaddr regname ##_start;      \
-    hwaddr regname ##_length;     \
-    MemoryRegion regname ##_mem
-
-#define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120"
-
-#define GT64120_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE)
-
-typedef struct GT64120State {
-    PCIHostState parent_obj;
-
-    uint32_t regs[GT_REGS];
-    PCI_MAPPING_ENTRY(PCI0IO);
-    PCI_MAPPING_ENTRY(ISD);
-} GT64120State;
-
-/* Adjust range to avoid touching space which isn't mappable via PCI */
-/* XXX: Hardcoded values for Malta: 0x1e000000 - 0x1f100000
-                                    0x1fc00000 - 0x1fd00000  */
-static void check_reserved_space (hwaddr *start,
-                                  hwaddr *length)
-{
-    hwaddr begin = *start;
-    hwaddr end = *start + *length;
-
-    if (end >= 0x1e000000LL && end < 0x1f100000LL)
-        end = 0x1e000000LL;
-    if (begin >= 0x1e000000LL && begin < 0x1f100000LL)
-        begin = 0x1f100000LL;
-    if (end >= 0x1fc00000LL && end < 0x1fd00000LL)
-        end = 0x1fc00000LL;
-    if (begin >= 0x1fc00000LL && begin < 0x1fd00000LL)
-        begin = 0x1fd00000LL;
-    /* XXX: This is broken when a reserved range splits the requested range */
-    if (end >= 0x1f100000LL && begin < 0x1e000000LL)
-        end = 0x1e000000LL;
-    if (end >= 0x1fd00000LL && begin < 0x1fc00000LL)
-        end = 0x1fc00000LL;
-
-    *start = begin;
-    *length = end - begin;
-}
-
-static void gt64120_isd_mapping(GT64120State *s)
-{
-    hwaddr start = s->regs[GT_ISD] << 21;
-    hwaddr length = 0x1000;
-
-    if (s->ISD_length) {
-        memory_region_del_subregion(get_system_memory(), &s->ISD_mem);
-    }
-    check_reserved_space(&start, &length);
-    length = 0x1000;
-    /* Map new address */
-    DPRINTF("ISD: "TARGET_FMT_plx"@"TARGET_FMT_plx
-        " -> "TARGET_FMT_plx"@"TARGET_FMT_plx"\n",
-        s->ISD_length, s->ISD_start, length, start);
-    s->ISD_start = start;
-    s->ISD_length = length;
-    memory_region_add_subregion(get_system_memory(), s->ISD_start, &s->ISD_mem);
-}
-
-static void gt64120_pci_mapping(GT64120State *s)
-{
-    /* Update IO mapping */
-    if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
-    {
-      /* Unmap old IO address */
-      if (s->PCI0IO_length)
-      {
-          memory_region_del_subregion(get_system_memory(), &s->PCI0IO_mem);
-          memory_region_destroy(&s->PCI0IO_mem);
-      }
-      /* Map new IO address */
-      s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
-      s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
-      isa_mem_base = s->PCI0IO_start;
-      if (s->PCI0IO_length) {
-          isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length);
-          memory_region_add_subregion(get_system_memory(), s->PCI0IO_start,
-                                      &s->PCI0IO_mem);
-      }
-    }
-}
-
-static void gt64120_writel (void *opaque, hwaddr addr,
-                            uint64_t val, unsigned size)
-{
-    GT64120State *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    uint32_t saddr;
-
-    if (!(s->regs[GT_CPU] & 0x00001000))
-        val = bswap32(val);
-
-    saddr = (addr & 0xfff) >> 2;
-    switch (saddr) {
-
-    /* CPU Configuration */
-    case GT_CPU:
-        s->regs[GT_CPU] = val;
-        break;
-    case GT_MULTI:
-       /* Read-only register as only one GT64xxx is present on the CPU bus */
-        break;
-
-    /* CPU Address Decode */
-    case GT_PCI0IOLD:
-        s->regs[GT_PCI0IOLD]    = val & 0x00007fff;
-        s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
-        gt64120_pci_mapping(s);
-        break;
-    case GT_PCI0M0LD:
-        s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
-        s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
-        break;
-    case GT_PCI0M1LD:
-        s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
-        s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
-        break;
-    case GT_PCI1IOLD:
-        s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
-        s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
-        break;
-    case GT_PCI1M0LD:
-        s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
-        s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
-        break;
-    case GT_PCI1M1LD:
-        s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
-        s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
-        break;
-    case GT_PCI0IOHD:
-        s->regs[saddr] = val & 0x0000007f;
-        gt64120_pci_mapping(s);
-        break;
-    case GT_PCI0M0HD:
-    case GT_PCI0M1HD:
-    case GT_PCI1IOHD:
-    case GT_PCI1M0HD:
-    case GT_PCI1M1HD:
-        s->regs[saddr] = val & 0x0000007f;
-        break;
-    case GT_ISD:
-        s->regs[saddr] = val & 0x00007fff;
-        gt64120_isd_mapping(s);
-        break;
-
-    case GT_PCI0IOREMAP:
-    case GT_PCI0M0REMAP:
-    case GT_PCI0M1REMAP:
-    case GT_PCI1IOREMAP:
-    case GT_PCI1M0REMAP:
-    case GT_PCI1M1REMAP:
-        s->regs[saddr] = val & 0x000007ff;
-        break;
-
-    /* CPU Error Report */
-    case GT_CPUERR_ADDRLO:
-    case GT_CPUERR_ADDRHI:
-    case GT_CPUERR_DATALO:
-    case GT_CPUERR_DATAHI:
-    case GT_CPUERR_PARITY:
-       /* Read-only registers, do nothing */
-        break;
-
-    /* CPU Sync Barrier */
-    case GT_PCI0SYNC:
-    case GT_PCI1SYNC:
-       /* Read-only registers, do nothing */
-        break;
-
-    /* SDRAM and Device Address Decode */
-    case GT_SCS0LD:
-    case GT_SCS0HD:
-    case GT_SCS1LD:
-    case GT_SCS1HD:
-    case GT_SCS2LD:
-    case GT_SCS2HD:
-    case GT_SCS3LD:
-    case GT_SCS3HD:
-    case GT_CS0LD:
-    case GT_CS0HD:
-    case GT_CS1LD:
-    case GT_CS1HD:
-    case GT_CS2LD:
-    case GT_CS2HD:
-    case GT_CS3LD:
-    case GT_CS3HD:
-    case GT_BOOTLD:
-    case GT_BOOTHD:
-    case GT_ADERR:
-    /* SDRAM Configuration */
-    case GT_SDRAM_CFG:
-    case GT_SDRAM_OPMODE:
-    case GT_SDRAM_BM:
-    case GT_SDRAM_ADDRDECODE:
-        /* Accept and ignore SDRAM interleave configuration */
-        s->regs[saddr] = val;
-        break;
-
-    /* Device Parameters */
-    case GT_DEV_B0:
-    case GT_DEV_B1:
-    case GT_DEV_B2:
-    case GT_DEV_B3:
-    case GT_DEV_BOOT:
-        /* Not implemented */
-        DPRINTF ("Unimplemented device register offset 0x%x\n", saddr << 2);
-        break;
-
-    /* ECC */
-    case GT_ECC_ERRDATALO:
-    case GT_ECC_ERRDATAHI:
-    case GT_ECC_MEM:
-    case GT_ECC_CALC:
-    case GT_ECC_ERRADDR:
-        /* Read-only registers, do nothing */
-        break;
-
-    /* DMA Record */
-    case GT_DMA0_CNT:
-    case GT_DMA1_CNT:
-    case GT_DMA2_CNT:
-    case GT_DMA3_CNT:
-    case GT_DMA0_SA:
-    case GT_DMA1_SA:
-    case GT_DMA2_SA:
-    case GT_DMA3_SA:
-    case GT_DMA0_DA:
-    case GT_DMA1_DA:
-    case GT_DMA2_DA:
-    case GT_DMA3_DA:
-    case GT_DMA0_NEXT:
-    case GT_DMA1_NEXT:
-    case GT_DMA2_NEXT:
-    case GT_DMA3_NEXT:
-    case GT_DMA0_CUR:
-    case GT_DMA1_CUR:
-    case GT_DMA2_CUR:
-    case GT_DMA3_CUR:
-        /* Not implemented */
-        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
-        break;
-
-    /* DMA Channel Control */
-    case GT_DMA0_CTRL:
-    case GT_DMA1_CTRL:
-    case GT_DMA2_CTRL:
-    case GT_DMA3_CTRL:
-        /* Not implemented */
-        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
-        break;
-
-    /* DMA Arbiter */
-    case GT_DMA_ARB:
-        /* Not implemented */
-        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
-        break;
-
-    /* Timer/Counter */
-    case GT_TC0:
-    case GT_TC1:
-    case GT_TC2:
-    case GT_TC3:
-    case GT_TC_CONTROL:
-        /* Not implemented */
-        DPRINTF ("Unimplemented timer register offset 0x%x\n", saddr << 2);
-        break;
-
-    /* PCI Internal */
-    case GT_PCI0_CMD:
-    case GT_PCI1_CMD:
-        s->regs[saddr] = val & 0x0401fc0f;
-        break;
-    case GT_PCI0_TOR:
-    case GT_PCI0_BS_SCS10:
-    case GT_PCI0_BS_SCS32:
-    case GT_PCI0_BS_CS20:
-    case GT_PCI0_BS_CS3BT:
-    case GT_PCI1_IACK:
-    case GT_PCI0_IACK:
-    case GT_PCI0_BARE:
-    case GT_PCI0_PREFMBR:
-    case GT_PCI0_SCS10_BAR:
-    case GT_PCI0_SCS32_BAR:
-    case GT_PCI0_CS20_BAR:
-    case GT_PCI0_CS3BT_BAR:
-    case GT_PCI0_SSCS10_BAR:
-    case GT_PCI0_SSCS32_BAR:
-    case GT_PCI0_SCS3BT_BAR:
-    case GT_PCI1_TOR:
-    case GT_PCI1_BS_SCS10:
-    case GT_PCI1_BS_SCS32:
-    case GT_PCI1_BS_CS20:
-    case GT_PCI1_BS_CS3BT:
-    case GT_PCI1_BARE:
-    case GT_PCI1_PREFMBR:
-    case GT_PCI1_SCS10_BAR:
-    case GT_PCI1_SCS32_BAR:
-    case GT_PCI1_CS20_BAR:
-    case GT_PCI1_CS3BT_BAR:
-    case GT_PCI1_SSCS10_BAR:
-    case GT_PCI1_SSCS32_BAR:
-    case GT_PCI1_SCS3BT_BAR:
-    case GT_PCI1_CFGADDR:
-    case GT_PCI1_CFGDATA:
-        /* not implemented */
-        break;
-    case GT_PCI0_CFGADDR:
-        phb->config_reg = val & 0x80fffffc;
-        break;
-    case GT_PCI0_CFGDATA:
-        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
-            val = bswap32(val);
-        }
-        if (phb->config_reg & (1u << 31)) {
-            pci_data_write(phb->bus, phb->config_reg, val, 4);
-        }
-        break;
-
-    /* Interrupts */
-    case GT_INTRCAUSE:
-        /* not really implemented */
-        s->regs[saddr] = ~(~(s->regs[saddr]) | ~(val & 0xfffffffe));
-        s->regs[saddr] |= !!(s->regs[saddr] & 0xfffffffe);
-        DPRINTF("INTRCAUSE %" PRIx64 "\n", val);
-        break;
-    case GT_INTRMASK:
-        s->regs[saddr] = val & 0x3c3ffffe;
-        DPRINTF("INTRMASK %" PRIx64 "\n", val);
-        break;
-    case GT_PCI0_ICMASK:
-        s->regs[saddr] = val & 0x03fffffe;
-        DPRINTF("ICMASK %" PRIx64 "\n", val);
-        break;
-    case GT_PCI0_SERR0MASK:
-        s->regs[saddr] = val & 0x0000003f;
-        DPRINTF("SERR0MASK %" PRIx64 "\n", val);
-        break;
-
-    /* Reserved when only PCI_0 is configured. */
-    case GT_HINTRCAUSE:
-    case GT_CPU_INTSEL:
-    case GT_PCI0_INTSEL:
-    case GT_HINTRMASK:
-    case GT_PCI0_HICMASK:
-    case GT_PCI1_SERR1MASK:
-        /* not implemented */
-        break;
-
-    /* SDRAM Parameters */
-    case GT_SDRAM_B0:
-    case GT_SDRAM_B1:
-    case GT_SDRAM_B2:
-    case GT_SDRAM_B3:
-        /* We don't simulate electrical parameters of the SDRAM.
-           Accept, but ignore the values. */
-        s->regs[saddr] = val;
-        break;
-
-    default:
-        DPRINTF ("Bad register offset 0x%x\n", (int)addr);
-        break;
-    }
-}
-
-static uint64_t gt64120_readl (void *opaque,
-                               hwaddr addr, unsigned size)
-{
-    GT64120State *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    uint32_t val;
-    uint32_t saddr;
-
-    saddr = (addr & 0xfff) >> 2;
-    switch (saddr) {
-
-    /* CPU Configuration */
-    case GT_MULTI:
-        /* Only one GT64xxx is present on the CPU bus, return
-           the initial value */
-        val = s->regs[saddr];
-        break;
-
-    /* CPU Error Report */
-    case GT_CPUERR_ADDRLO:
-    case GT_CPUERR_ADDRHI:
-    case GT_CPUERR_DATALO:
-    case GT_CPUERR_DATAHI:
-    case GT_CPUERR_PARITY:
-        /* Emulated memory has no error, always return the initial
-           values */
-        val = s->regs[saddr];
-        break;
-
-    /* CPU Sync Barrier */
-    case GT_PCI0SYNC:
-    case GT_PCI1SYNC:
-        /* Reading those register should empty all FIFO on the PCI
-           bus, which are not emulated. The return value should be
-           a random value that should be ignored. */
-        val = 0xc000ffee;
-        break;
-
-    /* ECC */
-    case GT_ECC_ERRDATALO:
-    case GT_ECC_ERRDATAHI:
-    case GT_ECC_MEM:
-    case GT_ECC_CALC:
-    case GT_ECC_ERRADDR:
-        /* Emulated memory has no error, always return the initial
-           values */
-        val = s->regs[saddr];
-        break;
-
-    case GT_CPU:
-    case GT_SCS10LD:
-    case GT_SCS10HD:
-    case GT_SCS32LD:
-    case GT_SCS32HD:
-    case GT_CS20LD:
-    case GT_CS20HD:
-    case GT_CS3BOOTLD:
-    case GT_CS3BOOTHD:
-    case GT_SCS10AR:
-    case GT_SCS32AR:
-    case GT_CS20R:
-    case GT_CS3BOOTR:
-    case GT_PCI0IOLD:
-    case GT_PCI0M0LD:
-    case GT_PCI0M1LD:
-    case GT_PCI1IOLD:
-    case GT_PCI1M0LD:
-    case GT_PCI1M1LD:
-    case GT_PCI0IOHD:
-    case GT_PCI0M0HD:
-    case GT_PCI0M1HD:
-    case GT_PCI1IOHD:
-    case GT_PCI1M0HD:
-    case GT_PCI1M1HD:
-    case GT_PCI0IOREMAP:
-    case GT_PCI0M0REMAP:
-    case GT_PCI0M1REMAP:
-    case GT_PCI1IOREMAP:
-    case GT_PCI1M0REMAP:
-    case GT_PCI1M1REMAP:
-    case GT_ISD:
-        val = s->regs[saddr];
-        break;
-    case GT_PCI0_IACK:
-        /* Read the IRQ number */
-        val = pic_read_irq(isa_pic);
-        break;
-
-    /* SDRAM and Device Address Decode */
-    case GT_SCS0LD:
-    case GT_SCS0HD:
-    case GT_SCS1LD:
-    case GT_SCS1HD:
-    case GT_SCS2LD:
-    case GT_SCS2HD:
-    case GT_SCS3LD:
-    case GT_SCS3HD:
-    case GT_CS0LD:
-    case GT_CS0HD:
-    case GT_CS1LD:
-    case GT_CS1HD:
-    case GT_CS2LD:
-    case GT_CS2HD:
-    case GT_CS3LD:
-    case GT_CS3HD:
-    case GT_BOOTLD:
-    case GT_BOOTHD:
-    case GT_ADERR:
-        val = s->regs[saddr];
-        break;
-
-    /* SDRAM Configuration */
-    case GT_SDRAM_CFG:
-    case GT_SDRAM_OPMODE:
-    case GT_SDRAM_BM:
-    case GT_SDRAM_ADDRDECODE:
-        val = s->regs[saddr];
-        break;
-
-    /* SDRAM Parameters */
-    case GT_SDRAM_B0:
-    case GT_SDRAM_B1:
-    case GT_SDRAM_B2:
-    case GT_SDRAM_B3:
-        /* We don't simulate electrical parameters of the SDRAM.
-           Just return the last written value. */
-        val = s->regs[saddr];
-        break;
-
-    /* Device Parameters */
-    case GT_DEV_B0:
-    case GT_DEV_B1:
-    case GT_DEV_B2:
-    case GT_DEV_B3:
-    case GT_DEV_BOOT:
-        val = s->regs[saddr];
-        break;
-
-    /* DMA Record */
-    case GT_DMA0_CNT:
-    case GT_DMA1_CNT:
-    case GT_DMA2_CNT:
-    case GT_DMA3_CNT:
-    case GT_DMA0_SA:
-    case GT_DMA1_SA:
-    case GT_DMA2_SA:
-    case GT_DMA3_SA:
-    case GT_DMA0_DA:
-    case GT_DMA1_DA:
-    case GT_DMA2_DA:
-    case GT_DMA3_DA:
-    case GT_DMA0_NEXT:
-    case GT_DMA1_NEXT:
-    case GT_DMA2_NEXT:
-    case GT_DMA3_NEXT:
-    case GT_DMA0_CUR:
-    case GT_DMA1_CUR:
-    case GT_DMA2_CUR:
-    case GT_DMA3_CUR:
-        val = s->regs[saddr];
-        break;
-
-    /* DMA Channel Control */
-    case GT_DMA0_CTRL:
-    case GT_DMA1_CTRL:
-    case GT_DMA2_CTRL:
-    case GT_DMA3_CTRL:
-        val = s->regs[saddr];
-        break;
-
-    /* DMA Arbiter */
-    case GT_DMA_ARB:
-        val = s->regs[saddr];
-        break;
-
-    /* Timer/Counter */
-    case GT_TC0:
-    case GT_TC1:
-    case GT_TC2:
-    case GT_TC3:
-    case GT_TC_CONTROL:
-        val = s->regs[saddr];
-        break;
-
-    /* PCI Internal */
-    case GT_PCI0_CFGADDR:
-        val = phb->config_reg;
-        break;
-    case GT_PCI0_CFGDATA:
-        if (!(phb->config_reg & (1 << 31))) {
-            val = 0xffffffff;
-        } else {
-            val = pci_data_read(phb->bus, phb->config_reg, 4);
-        }
-        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
-            val = bswap32(val);
-        }
-        break;
-
-    case GT_PCI0_CMD:
-    case GT_PCI0_TOR:
-    case GT_PCI0_BS_SCS10:
-    case GT_PCI0_BS_SCS32:
-    case GT_PCI0_BS_CS20:
-    case GT_PCI0_BS_CS3BT:
-    case GT_PCI1_IACK:
-    case GT_PCI0_BARE:
-    case GT_PCI0_PREFMBR:
-    case GT_PCI0_SCS10_BAR:
-    case GT_PCI0_SCS32_BAR:
-    case GT_PCI0_CS20_BAR:
-    case GT_PCI0_CS3BT_BAR:
-    case GT_PCI0_SSCS10_BAR:
-    case GT_PCI0_SSCS32_BAR:
-    case GT_PCI0_SCS3BT_BAR:
-    case GT_PCI1_CMD:
-    case GT_PCI1_TOR:
-    case GT_PCI1_BS_SCS10:
-    case GT_PCI1_BS_SCS32:
-    case GT_PCI1_BS_CS20:
-    case GT_PCI1_BS_CS3BT:
-    case GT_PCI1_BARE:
-    case GT_PCI1_PREFMBR:
-    case GT_PCI1_SCS10_BAR:
-    case GT_PCI1_SCS32_BAR:
-    case GT_PCI1_CS20_BAR:
-    case GT_PCI1_CS3BT_BAR:
-    case GT_PCI1_SSCS10_BAR:
-    case GT_PCI1_SSCS32_BAR:
-    case GT_PCI1_SCS3BT_BAR:
-    case GT_PCI1_CFGADDR:
-    case GT_PCI1_CFGDATA:
-        val = s->regs[saddr];
-        break;
-
-    /* Interrupts */
-    case GT_INTRCAUSE:
-        val = s->regs[saddr];
-        DPRINTF("INTRCAUSE %x\n", val);
-        break;
-    case GT_INTRMASK:
-        val = s->regs[saddr];
-        DPRINTF("INTRMASK %x\n", val);
-        break;
-    case GT_PCI0_ICMASK:
-        val = s->regs[saddr];
-        DPRINTF("ICMASK %x\n", val);
-        break;
-    case GT_PCI0_SERR0MASK:
-        val = s->regs[saddr];
-        DPRINTF("SERR0MASK %x\n", val);
-        break;
-
-    /* Reserved when only PCI_0 is configured. */
-    case GT_HINTRCAUSE:
-    case GT_CPU_INTSEL:
-    case GT_PCI0_INTSEL:
-    case GT_HINTRMASK:
-    case GT_PCI0_HICMASK:
-    case GT_PCI1_SERR1MASK:
-        val = s->regs[saddr];
-        break;
-
-    default:
-        val = s->regs[saddr];
-        DPRINTF ("Bad register offset 0x%x\n", (int)addr);
-        break;
-    }
-
-    if (!(s->regs[GT_CPU] & 0x00001000))
-        val = bswap32(val);
-
-    return val;
-}
-
-static const MemoryRegionOps isd_mem_ops = {
-    .read = gt64120_readl,
-    .write = gt64120_writel,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    int slot;
-
-    slot = (pci_dev->devfn >> 3);
-
-    switch (slot) {
-      /* PIIX4 USB */
-      case 10:
-        return 3;
-      /* AMD 79C973 Ethernet */
-      case 11:
-        return 1;
-      /* Crystal 4281 Sound */
-      case 12:
-        return 2;
-      /* PCI slot 1 to 4 */
-      case 18 ... 21:
-        return ((slot - 18) + irq_num) & 0x03;
-      /* Unknown device, don't do any translation */
-      default:
-        return irq_num;
-    }
-}
-
-static int pci_irq_levels[4];
-
-static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
-{
-    int i, pic_irq, pic_level;
-    qemu_irq *pic = opaque;
-
-    pci_irq_levels[irq_num] = level;
-
-    /* now we change the pic irq level according to the piix irq mappings */
-    /* XXX: optimize */
-    pic_irq = piix4_dev->config[0x60 + irq_num];
-    if (pic_irq < 16) {
-        /* The pic level is the logical OR of all the PCI irqs mapped
-           to it */
-        pic_level = 0;
-        for (i = 0; i < 4; i++) {
-            if (pic_irq == piix4_dev->config[0x60 + i])
-                pic_level |= pci_irq_levels[i];
-        }
-        qemu_set_irq(pic[pic_irq], pic_level);
-    }
-}
-
-
-static void gt64120_reset(void *opaque)
-{
-    GT64120State *s = opaque;
-
-    /* FIXME: Malta specific hw assumptions ahead */
-
-    /* CPU Configuration */
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->regs[GT_CPU]           = 0x00000000;
-#else
-    s->regs[GT_CPU]           = 0x00001000;
-#endif
-    s->regs[GT_MULTI]         = 0x00000003;
-
-    /* CPU Address decode */
-    s->regs[GT_SCS10LD]       = 0x00000000;
-    s->regs[GT_SCS10HD]       = 0x00000007;
-    s->regs[GT_SCS32LD]       = 0x00000008;
-    s->regs[GT_SCS32HD]       = 0x0000000f;
-    s->regs[GT_CS20LD]        = 0x000000e0;
-    s->regs[GT_CS20HD]        = 0x00000070;
-    s->regs[GT_CS3BOOTLD]     = 0x000000f8;
-    s->regs[GT_CS3BOOTHD]     = 0x0000007f;
-
-    s->regs[GT_PCI0IOLD]      = 0x00000080;
-    s->regs[GT_PCI0IOHD]      = 0x0000000f;
-    s->regs[GT_PCI0M0LD]      = 0x00000090;
-    s->regs[GT_PCI0M0HD]      = 0x0000001f;
-    s->regs[GT_ISD]           = 0x000000a0;
-    s->regs[GT_PCI0M1LD]      = 0x00000790;
-    s->regs[GT_PCI0M1HD]      = 0x0000001f;
-    s->regs[GT_PCI1IOLD]      = 0x00000100;
-    s->regs[GT_PCI1IOHD]      = 0x0000000f;
-    s->regs[GT_PCI1M0LD]      = 0x00000110;
-    s->regs[GT_PCI1M0HD]      = 0x0000001f;
-    s->regs[GT_PCI1M1LD]      = 0x00000120;
-    s->regs[GT_PCI1M1HD]      = 0x0000002f;
-
-    s->regs[GT_SCS10AR]       = 0x00000000;
-    s->regs[GT_SCS32AR]       = 0x00000008;
-    s->regs[GT_CS20R]         = 0x000000e0;
-    s->regs[GT_CS3BOOTR]      = 0x000000f8;
-
-    s->regs[GT_PCI0IOREMAP]   = 0x00000080;
-    s->regs[GT_PCI0M0REMAP]   = 0x00000090;
-    s->regs[GT_PCI0M1REMAP]   = 0x00000790;
-    s->regs[GT_PCI1IOREMAP]   = 0x00000100;
-    s->regs[GT_PCI1M0REMAP]   = 0x00000110;
-    s->regs[GT_PCI1M1REMAP]   = 0x00000120;
-
-    /* CPU Error Report */
-    s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
-    s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
-    s->regs[GT_CPUERR_DATALO] = 0xffffffff;
-    s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
-    s->regs[GT_CPUERR_PARITY] = 0x000000ff;
-
-    /* CPU Sync Barrier */
-    s->regs[GT_PCI0SYNC]      = 0x00000000;
-    s->regs[GT_PCI1SYNC]      = 0x00000000;
-
-    /* SDRAM and Device Address Decode */
-    s->regs[GT_SCS0LD]        = 0x00000000;
-    s->regs[GT_SCS0HD]        = 0x00000007;
-    s->regs[GT_SCS1LD]        = 0x00000008;
-    s->regs[GT_SCS1HD]        = 0x0000000f;
-    s->regs[GT_SCS2LD]        = 0x00000010;
-    s->regs[GT_SCS2HD]        = 0x00000017;
-    s->regs[GT_SCS3LD]        = 0x00000018;
-    s->regs[GT_SCS3HD]        = 0x0000001f;
-    s->regs[GT_CS0LD]         = 0x000000c0;
-    s->regs[GT_CS0HD]         = 0x000000c7;
-    s->regs[GT_CS1LD]         = 0x000000c8;
-    s->regs[GT_CS1HD]         = 0x000000cf;
-    s->regs[GT_CS2LD]         = 0x000000d0;
-    s->regs[GT_CS2HD]         = 0x000000df;
-    s->regs[GT_CS3LD]         = 0x000000f0;
-    s->regs[GT_CS3HD]         = 0x000000fb;
-    s->regs[GT_BOOTLD]        = 0x000000fc;
-    s->regs[GT_BOOTHD]        = 0x000000ff;
-    s->regs[GT_ADERR]         = 0xffffffff;
-
-    /* SDRAM Configuration */
-    s->regs[GT_SDRAM_CFG]     = 0x00000200;
-    s->regs[GT_SDRAM_OPMODE]  = 0x00000000;
-    s->regs[GT_SDRAM_BM]      = 0x00000007;
-    s->regs[GT_SDRAM_ADDRDECODE] = 0x00000002;
-
-    /* SDRAM Parameters */
-    s->regs[GT_SDRAM_B0]      = 0x00000005;
-    s->regs[GT_SDRAM_B1]      = 0x00000005;
-    s->regs[GT_SDRAM_B2]      = 0x00000005;
-    s->regs[GT_SDRAM_B3]      = 0x00000005;
-
-    /* ECC */
-    s->regs[GT_ECC_ERRDATALO] = 0x00000000;
-    s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
-    s->regs[GT_ECC_MEM]       = 0x00000000;
-    s->regs[GT_ECC_CALC]      = 0x00000000;
-    s->regs[GT_ECC_ERRADDR]   = 0x00000000;
-
-    /* Device Parameters */
-    s->regs[GT_DEV_B0]        = 0x386fffff;
-    s->regs[GT_DEV_B1]        = 0x386fffff;
-    s->regs[GT_DEV_B2]        = 0x386fffff;
-    s->regs[GT_DEV_B3]        = 0x386fffff;
-    s->regs[GT_DEV_BOOT]      = 0x146fffff;
-
-    /* DMA registers are all zeroed at reset */
-
-    /* Timer/Counter */
-    s->regs[GT_TC0]           = 0xffffffff;
-    s->regs[GT_TC1]           = 0x00ffffff;
-    s->regs[GT_TC2]           = 0x00ffffff;
-    s->regs[GT_TC3]           = 0x00ffffff;
-    s->regs[GT_TC_CONTROL]    = 0x00000000;
-
-    /* PCI Internal */
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->regs[GT_PCI0_CMD]      = 0x00000000;
-#else
-    s->regs[GT_PCI0_CMD]      = 0x00010001;
-#endif
-    s->regs[GT_PCI0_TOR]      = 0x0000070f;
-    s->regs[GT_PCI0_BS_SCS10] = 0x00fff000;
-    s->regs[GT_PCI0_BS_SCS32] = 0x00fff000;
-    s->regs[GT_PCI0_BS_CS20]  = 0x01fff000;
-    s->regs[GT_PCI0_BS_CS3BT] = 0x00fff000;
-    s->regs[GT_PCI1_IACK]     = 0x00000000;
-    s->regs[GT_PCI0_IACK]     = 0x00000000;
-    s->regs[GT_PCI0_BARE]     = 0x0000000f;
-    s->regs[GT_PCI0_PREFMBR]  = 0x00000040;
-    s->regs[GT_PCI0_SCS10_BAR] = 0x00000000;
-    s->regs[GT_PCI0_SCS32_BAR] = 0x01000000;
-    s->regs[GT_PCI0_CS20_BAR] = 0x1c000000;
-    s->regs[GT_PCI0_CS3BT_BAR] = 0x1f000000;
-    s->regs[GT_PCI0_SSCS10_BAR] = 0x00000000;
-    s->regs[GT_PCI0_SSCS32_BAR] = 0x01000000;
-    s->regs[GT_PCI0_SCS3BT_BAR] = 0x1f000000;
-#ifdef TARGET_WORDS_BIGENDIAN
-    s->regs[GT_PCI1_CMD]      = 0x00000000;
-#else
-    s->regs[GT_PCI1_CMD]      = 0x00010001;
-#endif
-    s->regs[GT_PCI1_TOR]      = 0x0000070f;
-    s->regs[GT_PCI1_BS_SCS10] = 0x00fff000;
-    s->regs[GT_PCI1_BS_SCS32] = 0x00fff000;
-    s->regs[GT_PCI1_BS_CS20]  = 0x01fff000;
-    s->regs[GT_PCI1_BS_CS3BT] = 0x00fff000;
-    s->regs[GT_PCI1_BARE]     = 0x0000000f;
-    s->regs[GT_PCI1_PREFMBR]  = 0x00000040;
-    s->regs[GT_PCI1_SCS10_BAR] = 0x00000000;
-    s->regs[GT_PCI1_SCS32_BAR] = 0x01000000;
-    s->regs[GT_PCI1_CS20_BAR] = 0x1c000000;
-    s->regs[GT_PCI1_CS3BT_BAR] = 0x1f000000;
-    s->regs[GT_PCI1_SSCS10_BAR] = 0x00000000;
-    s->regs[GT_PCI1_SSCS32_BAR] = 0x01000000;
-    s->regs[GT_PCI1_SCS3BT_BAR] = 0x1f000000;
-    s->regs[GT_PCI1_CFGADDR]  = 0x00000000;
-    s->regs[GT_PCI1_CFGDATA]  = 0x00000000;
-    s->regs[GT_PCI0_CFGADDR]  = 0x00000000;
-
-    /* Interrupt registers are all zeroed at reset */
-
-    gt64120_isd_mapping(s);
-    gt64120_pci_mapping(s);
-}
-
-PCIBus *gt64120_register(qemu_irq *pic)
-{
-    GT64120State *d;
-    PCIHostState *phb;
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    d = GT64120_PCI_HOST_BRIDGE(dev);
-    phb = PCI_HOST_BRIDGE(dev);
-    phb->bus = pci_register_bus(dev, "pci",
-                                gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                pic,
-                                get_system_memory(),
-                                get_system_io(),
-                                PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
-    memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
-
-    pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
-    return phb->bus;
-}
-
-static int gt64120_init(SysBusDevice *dev)
-{
-    GT64120State *s;
-
-    s = GT64120_PCI_HOST_BRIDGE(dev);
-
-    /* FIXME: This value is computed from registers during reset, but some
-       devices (e.g. VGA card) need to know it when they are registered.
-       This also mean that changing the register to change the mapping
-       does not fully work. */
-    isa_mem_base = 0x10000000;
-    qemu_register_reset(gt64120_reset, s);
-    return 0;
-}
-
-static int gt64120_pci_init(PCIDevice *d)
-{
-    /* FIXME: Malta specific hw assumptions ahead */
-    pci_set_word(d->config + PCI_COMMAND, 0);
-    pci_set_word(d->config + PCI_STATUS,
-                 PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
-    pci_config_set_prog_interface(d->config, 0);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_3, 0x1f000000);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000);
-    pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001);
-    pci_set_byte(d->config + 0x3d, 0x01);
-
-    return 0;
-}
-
-static void gt64120_pci_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = gt64120_pci_init;
-    k->vendor_id = PCI_VENDOR_ID_MARVELL;
-    k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X;
-    k->revision = 0x10;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo gt64120_pci_info = {
-    .name          = "gt64120_pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = gt64120_pci_class_init,
-};
-
-static void gt64120_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = gt64120_init;
-}
-
-static const TypeInfo gt64120_info = {
-    .name          = TYPE_GT64120_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(GT64120State),
-    .class_init    = gt64120_class_init,
-};
-
-static void gt64120_pci_register_types(void)
-{
-    type_register_static(&gt64120_info);
-    type_register_static(&gt64120_pci_info);
-}
-
-type_init(gt64120_pci_register_types)
index af7f4b1fe59e7680388e3d3a532a51a6808291f9..a531d3aec68145b91628ce009d50186ff25565da 100644 (file)
@@ -1,8 +1,7 @@
 obj-y += apic_common.o apic.o
-obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
+obj-y += sga.o ioapic_common.o ioapic.o
 obj-y += vmport.o
 obj-y += debugexit.o
-obj-y += q35.o
 obj-y += kvm/
 obj-y += pc-testdev.o
 
index af4d1f947b36284ac0fa8eb5fcca0c2a12336fcc..0a652f85217d000287ba2216010b4f3b641e347f 100644 (file)
@@ -1,8 +1,4 @@
-obj-y += gt64xxx.o
-obj-$(CONFIG_FULONG) += bonito.o
-
-obj-y := $(addprefix ../,$(obj-y))
-
 obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-y += addr.o cputimer.o mips_int.o
 obj-$(CONFIG_FULONG) += mips_fulong2e.o
+obj-y += gt64xxx_pci.o
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
new file mode 100644 (file)
index 0000000..189e865
--- /dev/null
@@ -0,0 +1,1188 @@
+/*
+ * QEMU GT64120 PCI host
+ *
+ * Copyright (c) 2006,2007 Aurelien Jarno
+ *
+ * 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/hw.h"
+#include "hw/mips/mips.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/i386/pc.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define GT_REGS                        (0x1000 >> 2)
+
+/* CPU Configuration */
+#define GT_CPU                 (0x000 >> 2)
+#define GT_MULTI               (0x120 >> 2)
+
+/* CPU Address Decode */
+#define GT_SCS10LD             (0x008 >> 2)
+#define GT_SCS10HD             (0x010 >> 2)
+#define GT_SCS32LD             (0x018 >> 2)
+#define GT_SCS32HD             (0x020 >> 2)
+#define GT_CS20LD              (0x028 >> 2)
+#define GT_CS20HD              (0x030 >> 2)
+#define GT_CS3BOOTLD           (0x038 >> 2)
+#define GT_CS3BOOTHD           (0x040 >> 2)
+#define GT_PCI0IOLD                    (0x048 >> 2)
+#define GT_PCI0IOHD                    (0x050 >> 2)
+#define GT_PCI0M0LD                    (0x058 >> 2)
+#define GT_PCI0M0HD                    (0x060 >> 2)
+#define GT_PCI0M1LD                    (0x080 >> 2)
+#define GT_PCI0M1HD                    (0x088 >> 2)
+#define GT_PCI1IOLD                    (0x090 >> 2)
+#define GT_PCI1IOHD                    (0x098 >> 2)
+#define GT_PCI1M0LD                    (0x0a0 >> 2)
+#define GT_PCI1M0HD                    (0x0a8 >> 2)
+#define GT_PCI1M1LD                    (0x0b0 >> 2)
+#define GT_PCI1M1HD                    (0x0b8 >> 2)
+#define GT_ISD                 (0x068 >> 2)
+
+#define GT_SCS10AR             (0x0d0 >> 2)
+#define GT_SCS32AR             (0x0d8 >> 2)
+#define GT_CS20R               (0x0e0 >> 2)
+#define GT_CS3BOOTR                    (0x0e8 >> 2)
+
+#define GT_PCI0IOREMAP         (0x0f0 >> 2)
+#define GT_PCI0M0REMAP         (0x0f8 >> 2)
+#define GT_PCI0M1REMAP         (0x100 >> 2)
+#define GT_PCI1IOREMAP         (0x108 >> 2)
+#define GT_PCI1M0REMAP         (0x110 >> 2)
+#define GT_PCI1M1REMAP         (0x118 >> 2)
+
+/* CPU Error Report */
+#define GT_CPUERR_ADDRLO       (0x070 >> 2)
+#define GT_CPUERR_ADDRHI       (0x078 >> 2)
+#define GT_CPUERR_DATALO       (0x128 >> 2)            /* GT-64120A only  */
+#define GT_CPUERR_DATAHI       (0x130 >> 2)            /* GT-64120A only  */
+#define GT_CPUERR_PARITY       (0x138 >> 2)            /* GT-64120A only  */
+
+/* CPU Sync Barrier */
+#define GT_PCI0SYNC                    (0x0c0 >> 2)
+#define GT_PCI1SYNC                    (0x0c8 >> 2)
+
+/* SDRAM and Device Address Decode */
+#define GT_SCS0LD              (0x400 >> 2)
+#define GT_SCS0HD              (0x404 >> 2)
+#define GT_SCS1LD              (0x408 >> 2)
+#define GT_SCS1HD              (0x40c >> 2)
+#define GT_SCS2LD              (0x410 >> 2)
+#define GT_SCS2HD              (0x414 >> 2)
+#define GT_SCS3LD              (0x418 >> 2)
+#define GT_SCS3HD              (0x41c >> 2)
+#define GT_CS0LD               (0x420 >> 2)
+#define GT_CS0HD               (0x424 >> 2)
+#define GT_CS1LD               (0x428 >> 2)
+#define GT_CS1HD               (0x42c >> 2)
+#define GT_CS2LD               (0x430 >> 2)
+#define GT_CS2HD               (0x434 >> 2)
+#define GT_CS3LD               (0x438 >> 2)
+#define GT_CS3HD               (0x43c >> 2)
+#define GT_BOOTLD              (0x440 >> 2)
+#define GT_BOOTHD              (0x444 >> 2)
+#define GT_ADERR               (0x470 >> 2)
+
+/* SDRAM Configuration */
+#define GT_SDRAM_CFG           (0x448 >> 2)
+#define GT_SDRAM_OPMODE        (0x474 >> 2)
+#define GT_SDRAM_BM                    (0x478 >> 2)
+#define GT_SDRAM_ADDRDECODE            (0x47c >> 2)
+
+/* SDRAM Parameters */
+#define GT_SDRAM_B0                    (0x44c >> 2)
+#define GT_SDRAM_B1                    (0x450 >> 2)
+#define GT_SDRAM_B2                    (0x454 >> 2)
+#define GT_SDRAM_B3                    (0x458 >> 2)
+
+/* Device Parameters */
+#define GT_DEV_B0              (0x45c >> 2)
+#define GT_DEV_B1              (0x460 >> 2)
+#define GT_DEV_B2              (0x464 >> 2)
+#define GT_DEV_B3              (0x468 >> 2)
+#define GT_DEV_BOOT                    (0x46c >> 2)
+
+/* ECC */
+#define GT_ECC_ERRDATALO       (0x480 >> 2)            /* GT-64120A only  */
+#define GT_ECC_ERRDATAHI       (0x484 >> 2)            /* GT-64120A only  */
+#define GT_ECC_MEM             (0x488 >> 2)            /* GT-64120A only  */
+#define GT_ECC_CALC            (0x48c >> 2)            /* GT-64120A only  */
+#define GT_ECC_ERRADDR         (0x490 >> 2)            /* GT-64120A only  */
+
+/* DMA Record */
+#define GT_DMA0_CNT                    (0x800 >> 2)
+#define GT_DMA1_CNT                    (0x804 >> 2)
+#define GT_DMA2_CNT                    (0x808 >> 2)
+#define GT_DMA3_CNT                    (0x80c >> 2)
+#define GT_DMA0_SA             (0x810 >> 2)
+#define GT_DMA1_SA             (0x814 >> 2)
+#define GT_DMA2_SA             (0x818 >> 2)
+#define GT_DMA3_SA             (0x81c >> 2)
+#define GT_DMA0_DA             (0x820 >> 2)
+#define GT_DMA1_DA             (0x824 >> 2)
+#define GT_DMA2_DA             (0x828 >> 2)
+#define GT_DMA3_DA             (0x82c >> 2)
+#define GT_DMA0_NEXT           (0x830 >> 2)
+#define GT_DMA1_NEXT           (0x834 >> 2)
+#define GT_DMA2_NEXT           (0x838 >> 2)
+#define GT_DMA3_NEXT           (0x83c >> 2)
+#define GT_DMA0_CUR                    (0x870 >> 2)
+#define GT_DMA1_CUR                    (0x874 >> 2)
+#define GT_DMA2_CUR                    (0x878 >> 2)
+#define GT_DMA3_CUR                    (0x87c >> 2)
+
+/* DMA Channel Control */
+#define GT_DMA0_CTRL           (0x840 >> 2)
+#define GT_DMA1_CTRL           (0x844 >> 2)
+#define GT_DMA2_CTRL           (0x848 >> 2)
+#define GT_DMA3_CTRL           (0x84c >> 2)
+
+/* DMA Arbiter */
+#define GT_DMA_ARB             (0x860 >> 2)
+
+/* Timer/Counter */
+#define GT_TC0                 (0x850 >> 2)
+#define GT_TC1                 (0x854 >> 2)
+#define GT_TC2                 (0x858 >> 2)
+#define GT_TC3                 (0x85c >> 2)
+#define GT_TC_CONTROL          (0x864 >> 2)
+
+/* PCI Internal */
+#define GT_PCI0_CMD                    (0xc00 >> 2)
+#define GT_PCI0_TOR                    (0xc04 >> 2)
+#define GT_PCI0_BS_SCS10       (0xc08 >> 2)
+#define GT_PCI0_BS_SCS32       (0xc0c >> 2)
+#define GT_PCI0_BS_CS20        (0xc10 >> 2)
+#define GT_PCI0_BS_CS3BT       (0xc14 >> 2)
+#define GT_PCI1_IACK           (0xc30 >> 2)
+#define GT_PCI0_IACK           (0xc34 >> 2)
+#define GT_PCI0_BARE           (0xc3c >> 2)
+#define GT_PCI0_PREFMBR        (0xc40 >> 2)
+#define GT_PCI0_SCS10_BAR      (0xc48 >> 2)
+#define GT_PCI0_SCS32_BAR      (0xc4c >> 2)
+#define GT_PCI0_CS20_BAR       (0xc50 >> 2)
+#define GT_PCI0_CS3BT_BAR      (0xc54 >> 2)
+#define GT_PCI0_SSCS10_BAR     (0xc58 >> 2)
+#define GT_PCI0_SSCS32_BAR     (0xc5c >> 2)
+#define GT_PCI0_SCS3BT_BAR     (0xc64 >> 2)
+#define GT_PCI1_CMD                    (0xc80 >> 2)
+#define GT_PCI1_TOR                    (0xc84 >> 2)
+#define GT_PCI1_BS_SCS10       (0xc88 >> 2)
+#define GT_PCI1_BS_SCS32       (0xc8c >> 2)
+#define GT_PCI1_BS_CS20        (0xc90 >> 2)
+#define GT_PCI1_BS_CS3BT       (0xc94 >> 2)
+#define GT_PCI1_BARE           (0xcbc >> 2)
+#define GT_PCI1_PREFMBR        (0xcc0 >> 2)
+#define GT_PCI1_SCS10_BAR      (0xcc8 >> 2)
+#define GT_PCI1_SCS32_BAR      (0xccc >> 2)
+#define GT_PCI1_CS20_BAR       (0xcd0 >> 2)
+#define GT_PCI1_CS3BT_BAR      (0xcd4 >> 2)
+#define GT_PCI1_SSCS10_BAR     (0xcd8 >> 2)
+#define GT_PCI1_SSCS32_BAR     (0xcdc >> 2)
+#define GT_PCI1_SCS3BT_BAR     (0xce4 >> 2)
+#define GT_PCI1_CFGADDR        (0xcf0 >> 2)
+#define GT_PCI1_CFGDATA        (0xcf4 >> 2)
+#define GT_PCI0_CFGADDR        (0xcf8 >> 2)
+#define GT_PCI0_CFGDATA        (0xcfc >> 2)
+
+/* Interrupts */
+#define GT_INTRCAUSE           (0xc18 >> 2)
+#define GT_INTRMASK                    (0xc1c >> 2)
+#define GT_PCI0_ICMASK         (0xc24 >> 2)
+#define GT_PCI0_SERR0MASK      (0xc28 >> 2)
+#define GT_CPU_INTSEL          (0xc70 >> 2)
+#define GT_PCI0_INTSEL         (0xc74 >> 2)
+#define GT_HINTRCAUSE          (0xc98 >> 2)
+#define GT_HINTRMASK           (0xc9c >> 2)
+#define GT_PCI0_HICMASK        (0xca4 >> 2)
+#define GT_PCI1_SERR1MASK      (0xca8 >> 2)
+
+#define PCI_MAPPING_ENTRY(regname)            \
+    hwaddr regname ##_start;      \
+    hwaddr regname ##_length;     \
+    MemoryRegion regname ##_mem
+
+#define TYPE_GT64120_PCI_HOST_BRIDGE "gt64120"
+
+#define GT64120_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(GT64120State, (obj), TYPE_GT64120_PCI_HOST_BRIDGE)
+
+typedef struct GT64120State {
+    PCIHostState parent_obj;
+
+    uint32_t regs[GT_REGS];
+    PCI_MAPPING_ENTRY(PCI0IO);
+    PCI_MAPPING_ENTRY(ISD);
+} GT64120State;
+
+/* Adjust range to avoid touching space which isn't mappable via PCI */
+/* XXX: Hardcoded values for Malta: 0x1e000000 - 0x1f100000
+                                    0x1fc00000 - 0x1fd00000  */
+static void check_reserved_space (hwaddr *start,
+                                  hwaddr *length)
+{
+    hwaddr begin = *start;
+    hwaddr end = *start + *length;
+
+    if (end >= 0x1e000000LL && end < 0x1f100000LL)
+        end = 0x1e000000LL;
+    if (begin >= 0x1e000000LL && begin < 0x1f100000LL)
+        begin = 0x1f100000LL;
+    if (end >= 0x1fc00000LL && end < 0x1fd00000LL)
+        end = 0x1fc00000LL;
+    if (begin >= 0x1fc00000LL && begin < 0x1fd00000LL)
+        begin = 0x1fd00000LL;
+    /* XXX: This is broken when a reserved range splits the requested range */
+    if (end >= 0x1f100000LL && begin < 0x1e000000LL)
+        end = 0x1e000000LL;
+    if (end >= 0x1fd00000LL && begin < 0x1fc00000LL)
+        end = 0x1fc00000LL;
+
+    *start = begin;
+    *length = end - begin;
+}
+
+static void gt64120_isd_mapping(GT64120State *s)
+{
+    hwaddr start = s->regs[GT_ISD] << 21;
+    hwaddr length = 0x1000;
+
+    if (s->ISD_length) {
+        memory_region_del_subregion(get_system_memory(), &s->ISD_mem);
+    }
+    check_reserved_space(&start, &length);
+    length = 0x1000;
+    /* Map new address */
+    DPRINTF("ISD: "TARGET_FMT_plx"@"TARGET_FMT_plx
+        " -> "TARGET_FMT_plx"@"TARGET_FMT_plx"\n",
+        s->ISD_length, s->ISD_start, length, start);
+    s->ISD_start = start;
+    s->ISD_length = length;
+    memory_region_add_subregion(get_system_memory(), s->ISD_start, &s->ISD_mem);
+}
+
+static void gt64120_pci_mapping(GT64120State *s)
+{
+    /* Update IO mapping */
+    if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
+    {
+      /* Unmap old IO address */
+      if (s->PCI0IO_length)
+      {
+          memory_region_del_subregion(get_system_memory(), &s->PCI0IO_mem);
+          memory_region_destroy(&s->PCI0IO_mem);
+      }
+      /* Map new IO address */
+      s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
+      s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
+      isa_mem_base = s->PCI0IO_start;
+      if (s->PCI0IO_length) {
+          isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length);
+          memory_region_add_subregion(get_system_memory(), s->PCI0IO_start,
+                                      &s->PCI0IO_mem);
+      }
+    }
+}
+
+static void gt64120_writel (void *opaque, hwaddr addr,
+                            uint64_t val, unsigned size)
+{
+    GT64120State *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    uint32_t saddr;
+
+    if (!(s->regs[GT_CPU] & 0x00001000))
+        val = bswap32(val);
+
+    saddr = (addr & 0xfff) >> 2;
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_CPU:
+        s->regs[GT_CPU] = val;
+        break;
+    case GT_MULTI:
+       /* Read-only register as only one GT64xxx is present on the CPU bus */
+        break;
+
+    /* CPU Address Decode */
+    case GT_PCI0IOLD:
+        s->regs[GT_PCI0IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M0LD:
+        s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
+        break;
+    case GT_PCI0M1LD:
+        s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
+        break;
+    case GT_PCI1IOLD:
+        s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
+        break;
+    case GT_PCI1M0LD:
+        s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
+        break;
+    case GT_PCI1M1LD:
+        s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
+        break;
+    case GT_PCI0IOHD:
+        s->regs[saddr] = val & 0x0000007f;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+        s->regs[saddr] = val & 0x0000007f;
+        break;
+    case GT_ISD:
+        s->regs[saddr] = val & 0x00007fff;
+        gt64120_isd_mapping(s);
+        break;
+
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        s->regs[saddr] = val & 0x000007ff;
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+       /* Read-only registers, do nothing */
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+       /* Read-only registers, do nothing */
+        break;
+
+    /* SDRAM and Device Address Decode */
+    case GT_SCS0LD:
+    case GT_SCS0HD:
+    case GT_SCS1LD:
+    case GT_SCS1HD:
+    case GT_SCS2LD:
+    case GT_SCS2HD:
+    case GT_SCS3LD:
+    case GT_SCS3HD:
+    case GT_CS0LD:
+    case GT_CS0HD:
+    case GT_CS1LD:
+    case GT_CS1HD:
+    case GT_CS2LD:
+    case GT_CS2HD:
+    case GT_CS3LD:
+    case GT_CS3HD:
+    case GT_BOOTLD:
+    case GT_BOOTHD:
+    case GT_ADERR:
+    /* SDRAM Configuration */
+    case GT_SDRAM_CFG:
+    case GT_SDRAM_OPMODE:
+    case GT_SDRAM_BM:
+    case GT_SDRAM_ADDRDECODE:
+        /* Accept and ignore SDRAM interleave configuration */
+        s->regs[saddr] = val;
+        break;
+
+    /* Device Parameters */
+    case GT_DEV_B0:
+    case GT_DEV_B1:
+    case GT_DEV_B2:
+    case GT_DEV_B3:
+    case GT_DEV_BOOT:
+        /* Not implemented */
+        DPRINTF ("Unimplemented device register offset 0x%x\n", saddr << 2);
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Read-only registers, do nothing */
+        break;
+
+    /* DMA Record */
+    case GT_DMA0_CNT:
+    case GT_DMA1_CNT:
+    case GT_DMA2_CNT:
+    case GT_DMA3_CNT:
+    case GT_DMA0_SA:
+    case GT_DMA1_SA:
+    case GT_DMA2_SA:
+    case GT_DMA3_SA:
+    case GT_DMA0_DA:
+    case GT_DMA1_DA:
+    case GT_DMA2_DA:
+    case GT_DMA3_DA:
+    case GT_DMA0_NEXT:
+    case GT_DMA1_NEXT:
+    case GT_DMA2_NEXT:
+    case GT_DMA3_NEXT:
+    case GT_DMA0_CUR:
+    case GT_DMA1_CUR:
+    case GT_DMA2_CUR:
+    case GT_DMA3_CUR:
+        /* Not implemented */
+        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
+        break;
+
+    /* DMA Channel Control */
+    case GT_DMA0_CTRL:
+    case GT_DMA1_CTRL:
+    case GT_DMA2_CTRL:
+    case GT_DMA3_CTRL:
+        /* Not implemented */
+        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
+        break;
+
+    /* DMA Arbiter */
+    case GT_DMA_ARB:
+        /* Not implemented */
+        DPRINTF ("Unimplemented DMA register offset 0x%x\n", saddr << 2);
+        break;
+
+    /* Timer/Counter */
+    case GT_TC0:
+    case GT_TC1:
+    case GT_TC2:
+    case GT_TC3:
+    case GT_TC_CONTROL:
+        /* Not implemented */
+        DPRINTF ("Unimplemented timer register offset 0x%x\n", saddr << 2);
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+        s->regs[saddr] = val & 0x0401fc0f;
+        break;
+    case GT_PCI0_TOR:
+    case GT_PCI0_BS_SCS10:
+    case GT_PCI0_BS_SCS32:
+    case GT_PCI0_BS_CS20:
+    case GT_PCI0_BS_CS3BT:
+    case GT_PCI1_IACK:
+    case GT_PCI0_IACK:
+    case GT_PCI0_BARE:
+    case GT_PCI0_PREFMBR:
+    case GT_PCI0_SCS10_BAR:
+    case GT_PCI0_SCS32_BAR:
+    case GT_PCI0_CS20_BAR:
+    case GT_PCI0_CS3BT_BAR:
+    case GT_PCI0_SSCS10_BAR:
+    case GT_PCI0_SSCS32_BAR:
+    case GT_PCI0_SCS3BT_BAR:
+    case GT_PCI1_TOR:
+    case GT_PCI1_BS_SCS10:
+    case GT_PCI1_BS_SCS32:
+    case GT_PCI1_BS_CS20:
+    case GT_PCI1_BS_CS3BT:
+    case GT_PCI1_BARE:
+    case GT_PCI1_PREFMBR:
+    case GT_PCI1_SCS10_BAR:
+    case GT_PCI1_SCS32_BAR:
+    case GT_PCI1_CS20_BAR:
+    case GT_PCI1_CS3BT_BAR:
+    case GT_PCI1_SSCS10_BAR:
+    case GT_PCI1_SSCS32_BAR:
+    case GT_PCI1_SCS3BT_BAR:
+    case GT_PCI1_CFGADDR:
+    case GT_PCI1_CFGDATA:
+        /* not implemented */
+        break;
+    case GT_PCI0_CFGADDR:
+        phb->config_reg = val & 0x80fffffc;
+        break;
+    case GT_PCI0_CFGDATA:
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
+            val = bswap32(val);
+        }
+        if (phb->config_reg & (1u << 31)) {
+            pci_data_write(phb->bus, phb->config_reg, val, 4);
+        }
+        break;
+
+    /* Interrupts */
+    case GT_INTRCAUSE:
+        /* not really implemented */
+        s->regs[saddr] = ~(~(s->regs[saddr]) | ~(val & 0xfffffffe));
+        s->regs[saddr] |= !!(s->regs[saddr] & 0xfffffffe);
+        DPRINTF("INTRCAUSE %" PRIx64 "\n", val);
+        break;
+    case GT_INTRMASK:
+        s->regs[saddr] = val & 0x3c3ffffe;
+        DPRINTF("INTRMASK %" PRIx64 "\n", val);
+        break;
+    case GT_PCI0_ICMASK:
+        s->regs[saddr] = val & 0x03fffffe;
+        DPRINTF("ICMASK %" PRIx64 "\n", val);
+        break;
+    case GT_PCI0_SERR0MASK:
+        s->regs[saddr] = val & 0x0000003f;
+        DPRINTF("SERR0MASK %" PRIx64 "\n", val);
+        break;
+
+    /* Reserved when only PCI_0 is configured. */
+    case GT_HINTRCAUSE:
+    case GT_CPU_INTSEL:
+    case GT_PCI0_INTSEL:
+    case GT_HINTRMASK:
+    case GT_PCI0_HICMASK:
+    case GT_PCI1_SERR1MASK:
+        /* not implemented */
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Accept, but ignore the values. */
+        s->regs[saddr] = val;
+        break;
+
+    default:
+        DPRINTF ("Bad register offset 0x%x\n", (int)addr);
+        break;
+    }
+}
+
+static uint64_t gt64120_readl (void *opaque,
+                               hwaddr addr, unsigned size)
+{
+    GT64120State *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    uint32_t val;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfff) >> 2;
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_MULTI:
+        /* Only one GT64xxx is present on the CPU bus, return
+           the initial value */
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+        /* Emulated memory has no error, always return the initial
+           values */
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+        /* Reading those register should empty all FIFO on the PCI
+           bus, which are not emulated. The return value should be
+           a random value that should be ignored. */
+        val = 0xc000ffee;
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Emulated memory has no error, always return the initial
+           values */
+        val = s->regs[saddr];
+        break;
+
+    case GT_CPU:
+    case GT_SCS10LD:
+    case GT_SCS10HD:
+    case GT_SCS32LD:
+    case GT_SCS32HD:
+    case GT_CS20LD:
+    case GT_CS20HD:
+    case GT_CS3BOOTLD:
+    case GT_CS3BOOTHD:
+    case GT_SCS10AR:
+    case GT_SCS32AR:
+    case GT_CS20R:
+    case GT_CS3BOOTR:
+    case GT_PCI0IOLD:
+    case GT_PCI0M0LD:
+    case GT_PCI0M1LD:
+    case GT_PCI1IOLD:
+    case GT_PCI1M0LD:
+    case GT_PCI1M1LD:
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+    case GT_ISD:
+        val = s->regs[saddr];
+        break;
+    case GT_PCI0_IACK:
+        /* Read the IRQ number */
+        val = pic_read_irq(isa_pic);
+        break;
+
+    /* SDRAM and Device Address Decode */
+    case GT_SCS0LD:
+    case GT_SCS0HD:
+    case GT_SCS1LD:
+    case GT_SCS1HD:
+    case GT_SCS2LD:
+    case GT_SCS2HD:
+    case GT_SCS3LD:
+    case GT_SCS3HD:
+    case GT_CS0LD:
+    case GT_CS0HD:
+    case GT_CS1LD:
+    case GT_CS1HD:
+    case GT_CS2LD:
+    case GT_CS2HD:
+    case GT_CS3LD:
+    case GT_CS3HD:
+    case GT_BOOTLD:
+    case GT_BOOTHD:
+    case GT_ADERR:
+        val = s->regs[saddr];
+        break;
+
+    /* SDRAM Configuration */
+    case GT_SDRAM_CFG:
+    case GT_SDRAM_OPMODE:
+    case GT_SDRAM_BM:
+    case GT_SDRAM_ADDRDECODE:
+        val = s->regs[saddr];
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Just return the last written value. */
+        val = s->regs[saddr];
+        break;
+
+    /* Device Parameters */
+    case GT_DEV_B0:
+    case GT_DEV_B1:
+    case GT_DEV_B2:
+    case GT_DEV_B3:
+    case GT_DEV_BOOT:
+        val = s->regs[saddr];
+        break;
+
+    /* DMA Record */
+    case GT_DMA0_CNT:
+    case GT_DMA1_CNT:
+    case GT_DMA2_CNT:
+    case GT_DMA3_CNT:
+    case GT_DMA0_SA:
+    case GT_DMA1_SA:
+    case GT_DMA2_SA:
+    case GT_DMA3_SA:
+    case GT_DMA0_DA:
+    case GT_DMA1_DA:
+    case GT_DMA2_DA:
+    case GT_DMA3_DA:
+    case GT_DMA0_NEXT:
+    case GT_DMA1_NEXT:
+    case GT_DMA2_NEXT:
+    case GT_DMA3_NEXT:
+    case GT_DMA0_CUR:
+    case GT_DMA1_CUR:
+    case GT_DMA2_CUR:
+    case GT_DMA3_CUR:
+        val = s->regs[saddr];
+        break;
+
+    /* DMA Channel Control */
+    case GT_DMA0_CTRL:
+    case GT_DMA1_CTRL:
+    case GT_DMA2_CTRL:
+    case GT_DMA3_CTRL:
+        val = s->regs[saddr];
+        break;
+
+    /* DMA Arbiter */
+    case GT_DMA_ARB:
+        val = s->regs[saddr];
+        break;
+
+    /* Timer/Counter */
+    case GT_TC0:
+    case GT_TC1:
+    case GT_TC2:
+    case GT_TC3:
+    case GT_TC_CONTROL:
+        val = s->regs[saddr];
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CFGADDR:
+        val = phb->config_reg;
+        break;
+    case GT_PCI0_CFGDATA:
+        if (!(phb->config_reg & (1 << 31))) {
+            val = 0xffffffff;
+        } else {
+            val = pci_data_read(phb->bus, phb->config_reg, 4);
+        }
+        if (!(s->regs[GT_PCI0_CMD] & 1) && (phb->config_reg & 0x00fff800)) {
+            val = bswap32(val);
+        }
+        break;
+
+    case GT_PCI0_CMD:
+    case GT_PCI0_TOR:
+    case GT_PCI0_BS_SCS10:
+    case GT_PCI0_BS_SCS32:
+    case GT_PCI0_BS_CS20:
+    case GT_PCI0_BS_CS3BT:
+    case GT_PCI1_IACK:
+    case GT_PCI0_BARE:
+    case GT_PCI0_PREFMBR:
+    case GT_PCI0_SCS10_BAR:
+    case GT_PCI0_SCS32_BAR:
+    case GT_PCI0_CS20_BAR:
+    case GT_PCI0_CS3BT_BAR:
+    case GT_PCI0_SSCS10_BAR:
+    case GT_PCI0_SSCS32_BAR:
+    case GT_PCI0_SCS3BT_BAR:
+    case GT_PCI1_CMD:
+    case GT_PCI1_TOR:
+    case GT_PCI1_BS_SCS10:
+    case GT_PCI1_BS_SCS32:
+    case GT_PCI1_BS_CS20:
+    case GT_PCI1_BS_CS3BT:
+    case GT_PCI1_BARE:
+    case GT_PCI1_PREFMBR:
+    case GT_PCI1_SCS10_BAR:
+    case GT_PCI1_SCS32_BAR:
+    case GT_PCI1_CS20_BAR:
+    case GT_PCI1_CS3BT_BAR:
+    case GT_PCI1_SSCS10_BAR:
+    case GT_PCI1_SSCS32_BAR:
+    case GT_PCI1_SCS3BT_BAR:
+    case GT_PCI1_CFGADDR:
+    case GT_PCI1_CFGDATA:
+        val = s->regs[saddr];
+        break;
+
+    /* Interrupts */
+    case GT_INTRCAUSE:
+        val = s->regs[saddr];
+        DPRINTF("INTRCAUSE %x\n", val);
+        break;
+    case GT_INTRMASK:
+        val = s->regs[saddr];
+        DPRINTF("INTRMASK %x\n", val);
+        break;
+    case GT_PCI0_ICMASK:
+        val = s->regs[saddr];
+        DPRINTF("ICMASK %x\n", val);
+        break;
+    case GT_PCI0_SERR0MASK:
+        val = s->regs[saddr];
+        DPRINTF("SERR0MASK %x\n", val);
+        break;
+
+    /* Reserved when only PCI_0 is configured. */
+    case GT_HINTRCAUSE:
+    case GT_CPU_INTSEL:
+    case GT_PCI0_INTSEL:
+    case GT_HINTRMASK:
+    case GT_PCI0_HICMASK:
+    case GT_PCI1_SERR1MASK:
+        val = s->regs[saddr];
+        break;
+
+    default:
+        val = s->regs[saddr];
+        DPRINTF ("Bad register offset 0x%x\n", (int)addr);
+        break;
+    }
+
+    if (!(s->regs[GT_CPU] & 0x00001000))
+        val = bswap32(val);
+
+    return val;
+}
+
+static const MemoryRegionOps isd_mem_ops = {
+    .read = gt64120_readl,
+    .write = gt64120_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot;
+
+    slot = (pci_dev->devfn >> 3);
+
+    switch (slot) {
+      /* PIIX4 USB */
+      case 10:
+        return 3;
+      /* AMD 79C973 Ethernet */
+      case 11:
+        return 1;
+      /* Crystal 4281 Sound */
+      case 12:
+        return 2;
+      /* PCI slot 1 to 4 */
+      case 18 ... 21:
+        return ((slot - 18) + irq_num) & 0x03;
+      /* Unknown device, don't do any translation */
+      default:
+        return irq_num;
+    }
+}
+
+static int pci_irq_levels[4];
+
+static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
+{
+    int i, pic_irq, pic_level;
+    qemu_irq *pic = opaque;
+
+    pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to the piix irq mappings */
+    /* XXX: optimize */
+    pic_irq = piix4_dev->config[0x60 + irq_num];
+    if (pic_irq < 16) {
+        /* The pic level is the logical OR of all the PCI irqs mapped
+           to it */
+        pic_level = 0;
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix4_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
+        qemu_set_irq(pic[pic_irq], pic_level);
+    }
+}
+
+
+static void gt64120_reset(void *opaque)
+{
+    GT64120State *s = opaque;
+
+    /* FIXME: Malta specific hw assumptions ahead */
+
+    /* CPU Configuration */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_CPU]           = 0x00000000;
+#else
+    s->regs[GT_CPU]           = 0x00001000;
+#endif
+    s->regs[GT_MULTI]         = 0x00000003;
+
+    /* CPU Address decode */
+    s->regs[GT_SCS10LD]       = 0x00000000;
+    s->regs[GT_SCS10HD]       = 0x00000007;
+    s->regs[GT_SCS32LD]       = 0x00000008;
+    s->regs[GT_SCS32HD]       = 0x0000000f;
+    s->regs[GT_CS20LD]        = 0x000000e0;
+    s->regs[GT_CS20HD]        = 0x00000070;
+    s->regs[GT_CS3BOOTLD]     = 0x000000f8;
+    s->regs[GT_CS3BOOTHD]     = 0x0000007f;
+
+    s->regs[GT_PCI0IOLD]      = 0x00000080;
+    s->regs[GT_PCI0IOHD]      = 0x0000000f;
+    s->regs[GT_PCI0M0LD]      = 0x00000090;
+    s->regs[GT_PCI0M0HD]      = 0x0000001f;
+    s->regs[GT_ISD]           = 0x000000a0;
+    s->regs[GT_PCI0M1LD]      = 0x00000790;
+    s->regs[GT_PCI0M1HD]      = 0x0000001f;
+    s->regs[GT_PCI1IOLD]      = 0x00000100;
+    s->regs[GT_PCI1IOHD]      = 0x0000000f;
+    s->regs[GT_PCI1M0LD]      = 0x00000110;
+    s->regs[GT_PCI1M0HD]      = 0x0000001f;
+    s->regs[GT_PCI1M1LD]      = 0x00000120;
+    s->regs[GT_PCI1M1HD]      = 0x0000002f;
+
+    s->regs[GT_SCS10AR]       = 0x00000000;
+    s->regs[GT_SCS32AR]       = 0x00000008;
+    s->regs[GT_CS20R]         = 0x000000e0;
+    s->regs[GT_CS3BOOTR]      = 0x000000f8;
+
+    s->regs[GT_PCI0IOREMAP]   = 0x00000080;
+    s->regs[GT_PCI0M0REMAP]   = 0x00000090;
+    s->regs[GT_PCI0M1REMAP]   = 0x00000790;
+    s->regs[GT_PCI1IOREMAP]   = 0x00000100;
+    s->regs[GT_PCI1M0REMAP]   = 0x00000110;
+    s->regs[GT_PCI1M1REMAP]   = 0x00000120;
+
+    /* CPU Error Report */
+    s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
+    s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
+    s->regs[GT_CPUERR_DATALO] = 0xffffffff;
+    s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
+    s->regs[GT_CPUERR_PARITY] = 0x000000ff;
+
+    /* CPU Sync Barrier */
+    s->regs[GT_PCI0SYNC]      = 0x00000000;
+    s->regs[GT_PCI1SYNC]      = 0x00000000;
+
+    /* SDRAM and Device Address Decode */
+    s->regs[GT_SCS0LD]        = 0x00000000;
+    s->regs[GT_SCS0HD]        = 0x00000007;
+    s->regs[GT_SCS1LD]        = 0x00000008;
+    s->regs[GT_SCS1HD]        = 0x0000000f;
+    s->regs[GT_SCS2LD]        = 0x00000010;
+    s->regs[GT_SCS2HD]        = 0x00000017;
+    s->regs[GT_SCS3LD]        = 0x00000018;
+    s->regs[GT_SCS3HD]        = 0x0000001f;
+    s->regs[GT_CS0LD]         = 0x000000c0;
+    s->regs[GT_CS0HD]         = 0x000000c7;
+    s->regs[GT_CS1LD]         = 0x000000c8;
+    s->regs[GT_CS1HD]         = 0x000000cf;
+    s->regs[GT_CS2LD]         = 0x000000d0;
+    s->regs[GT_CS2HD]         = 0x000000df;
+    s->regs[GT_CS3LD]         = 0x000000f0;
+    s->regs[GT_CS3HD]         = 0x000000fb;
+    s->regs[GT_BOOTLD]        = 0x000000fc;
+    s->regs[GT_BOOTHD]        = 0x000000ff;
+    s->regs[GT_ADERR]         = 0xffffffff;
+
+    /* SDRAM Configuration */
+    s->regs[GT_SDRAM_CFG]     = 0x00000200;
+    s->regs[GT_SDRAM_OPMODE]  = 0x00000000;
+    s->regs[GT_SDRAM_BM]      = 0x00000007;
+    s->regs[GT_SDRAM_ADDRDECODE] = 0x00000002;
+
+    /* SDRAM Parameters */
+    s->regs[GT_SDRAM_B0]      = 0x00000005;
+    s->regs[GT_SDRAM_B1]      = 0x00000005;
+    s->regs[GT_SDRAM_B2]      = 0x00000005;
+    s->regs[GT_SDRAM_B3]      = 0x00000005;
+
+    /* ECC */
+    s->regs[GT_ECC_ERRDATALO] = 0x00000000;
+    s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
+    s->regs[GT_ECC_MEM]       = 0x00000000;
+    s->regs[GT_ECC_CALC]      = 0x00000000;
+    s->regs[GT_ECC_ERRADDR]   = 0x00000000;
+
+    /* Device Parameters */
+    s->regs[GT_DEV_B0]        = 0x386fffff;
+    s->regs[GT_DEV_B1]        = 0x386fffff;
+    s->regs[GT_DEV_B2]        = 0x386fffff;
+    s->regs[GT_DEV_B3]        = 0x386fffff;
+    s->regs[GT_DEV_BOOT]      = 0x146fffff;
+
+    /* DMA registers are all zeroed at reset */
+
+    /* Timer/Counter */
+    s->regs[GT_TC0]           = 0xffffffff;
+    s->regs[GT_TC1]           = 0x00ffffff;
+    s->regs[GT_TC2]           = 0x00ffffff;
+    s->regs[GT_TC3]           = 0x00ffffff;
+    s->regs[GT_TC_CONTROL]    = 0x00000000;
+
+    /* PCI Internal */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_PCI0_CMD]      = 0x00000000;
+#else
+    s->regs[GT_PCI0_CMD]      = 0x00010001;
+#endif
+    s->regs[GT_PCI0_TOR]      = 0x0000070f;
+    s->regs[GT_PCI0_BS_SCS10] = 0x00fff000;
+    s->regs[GT_PCI0_BS_SCS32] = 0x00fff000;
+    s->regs[GT_PCI0_BS_CS20]  = 0x01fff000;
+    s->regs[GT_PCI0_BS_CS3BT] = 0x00fff000;
+    s->regs[GT_PCI1_IACK]     = 0x00000000;
+    s->regs[GT_PCI0_IACK]     = 0x00000000;
+    s->regs[GT_PCI0_BARE]     = 0x0000000f;
+    s->regs[GT_PCI0_PREFMBR]  = 0x00000040;
+    s->regs[GT_PCI0_SCS10_BAR] = 0x00000000;
+    s->regs[GT_PCI0_SCS32_BAR] = 0x01000000;
+    s->regs[GT_PCI0_CS20_BAR] = 0x1c000000;
+    s->regs[GT_PCI0_CS3BT_BAR] = 0x1f000000;
+    s->regs[GT_PCI0_SSCS10_BAR] = 0x00000000;
+    s->regs[GT_PCI0_SSCS32_BAR] = 0x01000000;
+    s->regs[GT_PCI0_SCS3BT_BAR] = 0x1f000000;
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_PCI1_CMD]      = 0x00000000;
+#else
+    s->regs[GT_PCI1_CMD]      = 0x00010001;
+#endif
+    s->regs[GT_PCI1_TOR]      = 0x0000070f;
+    s->regs[GT_PCI1_BS_SCS10] = 0x00fff000;
+    s->regs[GT_PCI1_BS_SCS32] = 0x00fff000;
+    s->regs[GT_PCI1_BS_CS20]  = 0x01fff000;
+    s->regs[GT_PCI1_BS_CS3BT] = 0x00fff000;
+    s->regs[GT_PCI1_BARE]     = 0x0000000f;
+    s->regs[GT_PCI1_PREFMBR]  = 0x00000040;
+    s->regs[GT_PCI1_SCS10_BAR] = 0x00000000;
+    s->regs[GT_PCI1_SCS32_BAR] = 0x01000000;
+    s->regs[GT_PCI1_CS20_BAR] = 0x1c000000;
+    s->regs[GT_PCI1_CS3BT_BAR] = 0x1f000000;
+    s->regs[GT_PCI1_SSCS10_BAR] = 0x00000000;
+    s->regs[GT_PCI1_SSCS32_BAR] = 0x01000000;
+    s->regs[GT_PCI1_SCS3BT_BAR] = 0x1f000000;
+    s->regs[GT_PCI1_CFGADDR]  = 0x00000000;
+    s->regs[GT_PCI1_CFGDATA]  = 0x00000000;
+    s->regs[GT_PCI0_CFGADDR]  = 0x00000000;
+
+    /* Interrupt registers are all zeroed at reset */
+
+    gt64120_isd_mapping(s);
+    gt64120_pci_mapping(s);
+}
+
+PCIBus *gt64120_register(qemu_irq *pic)
+{
+    GT64120State *d;
+    PCIHostState *phb;
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, TYPE_GT64120_PCI_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    d = GT64120_PCI_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
+    phb->bus = pci_register_bus(dev, "pci",
+                                gt64120_pci_set_irq, gt64120_pci_map_irq,
+                                pic,
+                                get_system_memory(),
+                                get_system_io(),
+                                PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
+    memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
+
+    pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
+    return phb->bus;
+}
+
+static int gt64120_init(SysBusDevice *dev)
+{
+    GT64120State *s;
+
+    s = GT64120_PCI_HOST_BRIDGE(dev);
+
+    /* FIXME: This value is computed from registers during reset, but some
+       devices (e.g. VGA card) need to know it when they are registered.
+       This also mean that changing the register to change the mapping
+       does not fully work. */
+    isa_mem_base = 0x10000000;
+    qemu_register_reset(gt64120_reset, s);
+    return 0;
+}
+
+static int gt64120_pci_init(PCIDevice *d)
+{
+    /* FIXME: Malta specific hw assumptions ahead */
+    pci_set_word(d->config + PCI_COMMAND, 0);
+    pci_set_word(d->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+    pci_config_set_prog_interface(d->config, 0);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_3, 0x1f000000);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000);
+    pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001);
+    pci_set_byte(d->config + 0x3d, 0x01);
+
+    return 0;
+}
+
+static void gt64120_pci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = gt64120_pci_init;
+    k->vendor_id = PCI_VENDOR_ID_MARVELL;
+    k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X;
+    k->revision = 0x10;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo gt64120_pci_info = {
+    .name          = "gt64120_pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = gt64120_pci_class_init,
+};
+
+static void gt64120_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = gt64120_init;
+}
+
+static const TypeInfo gt64120_info = {
+    .name          = TYPE_GT64120_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(GT64120State),
+    .class_init    = gt64120_class_init,
+};
+
+static void gt64120_pci_register_types(void)
+{
+    type_register_static(&gt64120_info);
+    type_register_static(&gt64120_pci_info);
+}
+
+type_init(gt64120_pci_register_types)
diff --git a/hw/pci-bridge/Makefile.objs b/hw/pci-bridge/Makefile.objs
new file mode 100644 (file)
index 0000000..5dd92d2
--- /dev/null
@@ -0,0 +1,3 @@
+common-obj-y += pci_bridge_dev.o
+common-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+common-obj-y += i82801b11.o
diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c
new file mode 100644 (file)
index 0000000..5807a92
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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.
+ */
+/*
+ * QEMU i82801b11 dmi-to-pci Bridge Emulation
+ *
+ *  Copyright (c) 2009, 2010, 2011
+ *                Isaku Yamahata <yamahata at valinux co jp>
+ *                VA Linux Systems Japan K.K.
+ *  Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ */
+
+#include "hw/pci/pci.h"
+#include "hw/i386/ich9.h"
+
+
+/*****************************************************************************/
+/* ICH9 DMI-to-PCI bridge */
+#define I82801ba_SSVID_OFFSET   0x50
+#define I82801ba_SSVID_SVID     0
+#define I82801ba_SSVID_SSID     0
+
+typedef struct I82801b11Bridge {
+    PCIBridge br;
+} I82801b11Bridge;
+
+static int i82801b11_bridge_initfn(PCIDevice *d)
+{
+    int rc;
+
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    if (rc < 0) {
+        return rc;
+    }
+
+    rc = pci_bridge_ssvid_init(d, I82801ba_SSVID_OFFSET,
+                               I82801ba_SSVID_SVID, I82801ba_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    pci_config_set_prog_interface(d->config, PCI_CLASS_BRDIGE_PCI_INF_SUB);
+    return 0;
+
+err_bridge:
+    pci_bridge_exitfn(d);
+
+    return rc;
+}
+
+static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_bridge = 1;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
+    k->revision = ICH9_D2P_A2_REVISION;
+    k->init = i82801b11_bridge_initfn;
+}
+
+static const TypeInfo i82801b11_bridge_info = {
+    .name          = "i82801b11-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(I82801b11Bridge),
+    .class_init    = i82801b11_bridge_class_init,
+};
+
+PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+    char buf[16];
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, true, "i82801b11-bridge");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+    qdev = &br->dev.qdev;
+
+    snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
+    pci_bridge_map_irq(br, buf, pci_swizzle_map_irq_fn);
+    qdev_init_nofail(qdev);
+
+    return pci_bridge_get_sec_bus(br);
+}
+
+static void d2pbr_register(void)
+{
+    type_register_static(&i82801b11_bridge_info);
+}
+
+type_init(d2pbr_register);
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
new file mode 100644 (file)
index 0000000..5cff61e
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * ioh3420.c
+ * Intel X58 north bridge IOH
+ * PCI Express root port device id 3420
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/ioh3420.h"
+
+#define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
+#define PCI_DEVICE_ID_IOH_REV           0x2
+#define IOH_EP_SSVID_OFFSET             0x40
+#define IOH_EP_SSVID_SVID               PCI_VENDOR_ID_INTEL
+#define IOH_EP_SSVID_SSID               0
+#define IOH_EP_MSI_OFFSET               0x60
+#define IOH_EP_MSI_SUPPORTED_FLAGS      PCI_MSI_FLAGS_MASKBIT
+#define IOH_EP_MSI_NR_VECTOR            2
+#define IOH_EP_EXP_OFFSET               0x90
+#define IOH_EP_AER_OFFSET               0x100
+
+/*
+ * If two MSI vector are allocated, Advanced Error Interrupt Message Number
+ * is 1. otherwise 0.
+ * 17.12.5.10 RPERRSTS,  32:27 bit Advanced Error Interrupt Message Number.
+ */
+static uint8_t ioh3420_aer_vector(const PCIDevice *d)
+{
+    switch (msi_nr_vectors_allocated(d)) {
+    case 1:
+        return 0;
+    case 2:
+        return 1;
+    case 4:
+    case 8:
+    case 16:
+    case 32:
+    default:
+        break;
+    }
+    abort();
+    return 0;
+}
+
+static void ioh3420_aer_vector_update(PCIDevice *d)
+{
+    pcie_aer_root_set_vector(d, ioh3420_aer_vector(d));
+}
+
+static void ioh3420_write_config(PCIDevice *d,
+                                   uint32_t address, uint32_t val, int len)
+{
+    uint32_t root_cmd =
+        pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
+
+    pci_bridge_write_config(d, address, val, len);
+    ioh3420_aer_vector_update(d);
+    pcie_cap_slot_write_config(d, address, val, len);
+    pcie_aer_write_config(d, address, val, len);
+    pcie_aer_root_write_config(d, address, val, len, root_cmd);
+}
+
+static void ioh3420_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+
+    ioh3420_aer_vector_update(d);
+    pcie_cap_root_reset(d);
+    pcie_cap_deverr_reset(d);
+    pcie_cap_slot_reset(d);
+    pcie_aer_root_reset(d);
+    pci_bridge_reset(qdev);
+    pci_bridge_disable_base_limit(d);
+}
+
+static int ioh3420_initfn(PCIDevice *d)
+{
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+    int rc;
+
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
+    if (rc < 0) {
+        return rc;
+    }
+
+    pcie_port_init_reg(d);
+
+    rc = pci_bridge_ssvid_init(d, IOH_EP_SSVID_OFFSET,
+                               IOH_EP_SSVID_SVID, IOH_EP_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
+                  IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
+                  IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = pcie_cap_init(d, IOH_EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port);
+    if (rc < 0) {
+        goto err_msi;
+    }
+    pcie_cap_deverr_init(d);
+    pcie_cap_slot_init(d, s->slot);
+    pcie_chassis_create(s->chassis);
+    rc = pcie_chassis_add_slot(s);
+    if (rc < 0) {
+        goto err_pcie_cap;
+    }
+    pcie_cap_root_init(d);
+    rc = pcie_aer_init(d, IOH_EP_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
+    pcie_aer_root_init(d);
+    ioh3420_aer_vector_update(d);
+    return 0;
+
+err:
+    pcie_chassis_del_slot(s);
+err_pcie_cap:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    pci_bridge_exitfn(d);
+    return rc;
+}
+
+static void ioh3420_exitfn(PCIDevice *d)
+{
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+
+    pcie_aer_exit(d);
+    pcie_chassis_del_slot(s);
+    pcie_cap_exit(d);
+    msi_uninit(d);
+    pci_bridge_exitfn(d);
+}
+
+PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
+                         const char *bus_name, pci_map_irq_fn map_irq,
+                         uint8_t port, uint8_t chassis, uint16_t slot)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, multifunction, "ioh3420");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+
+    qdev = &br->dev.qdev;
+    pci_bridge_map_irq(br, bus_name, map_irq);
+    qdev_prop_set_uint8(qdev, "port", port);
+    qdev_prop_set_uint8(qdev, "chassis", chassis);
+    qdev_prop_set_uint16(qdev, "slot", slot);
+    qdev_init_nofail(qdev);
+
+    return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
+}
+
+static const VMStateDescription vmstate_ioh3420 = {
+    .name = "ioh-3240-express-root-port",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = pcie_cap_slot_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
+        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
+                       vmstate_pcie_aer_log, PCIEAERLog),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property ioh3420_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+    port.br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ioh3420_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = ioh3420_write_config;
+    k->init = ioh3420_initfn;
+    k->exit = ioh3420_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_IOH_EPORT;
+    k->revision = PCI_DEVICE_ID_IOH_REV;
+    dc->desc = "Intel IOH device id 3420 PCIE Root Port";
+    dc->reset = ioh3420_reset;
+    dc->vmsd = &vmstate_ioh3420;
+    dc->props = ioh3420_properties;
+}
+
+static const TypeInfo ioh3420_info = {
+    .name          = "ioh3420",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIESlot),
+    .class_init    = ioh3420_class_init,
+};
+
+static void ioh3420_register_types(void)
+{
+    type_register_static(&ioh3420_info);
+}
+
+type_init(ioh3420_register_types)
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
new file mode 100644 (file)
index 0000000..971b432
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Standard PCI Bridge Device
+ *
+ * Copyright (c) 2011 Red Hat Inc. Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * http://www.pcisig.com/specifications/conventional/pci_to_pci_bridge_architecture/
+ *
+ * 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
+#include "exec/memory.h"
+#include "hw/pci/pci_bus.h"
+
+struct PCIBridgeDev {
+    PCIBridge bridge;
+    MemoryRegion bar;
+    uint8_t chassis_nr;
+#define PCI_BRIDGE_DEV_F_MSI_REQ 0
+    uint32_t flags;
+};
+typedef struct PCIBridgeDev PCIBridgeDev;
+
+static int pci_bridge_dev_initfn(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+    int err;
+
+    err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
+    if (err) {
+        goto bridge_error;
+    }
+    memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev));
+    err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
+    if (err) {
+        goto shpc_error;
+    }
+    err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
+    if (err) {
+        goto slotid_error;
+    }
+    if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
+        msi_supported) {
+        err = msi_init(dev, 0, 1, true, true);
+        if (err < 0) {
+            goto msi_error;
+        }
+    }
+    /* TODO: spec recommends using 64 bit prefetcheable BAR.
+     * Check whether that works well. */
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+                    PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
+    dev->config[PCI_INTERRUPT_PIN] = 0x1;
+    return 0;
+msi_error:
+    slotid_cap_cleanup(dev);
+slotid_error:
+    shpc_cleanup(dev, &bridge_dev->bar);
+shpc_error:
+    memory_region_destroy(&bridge_dev->bar);
+    pci_bridge_exitfn(dev);
+bridge_error:
+    return err;
+}
+
+static void pci_bridge_dev_exitfn(PCIDevice *dev)
+{
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+    if (msi_present(dev)) {
+        msi_uninit(dev);
+    }
+    slotid_cap_cleanup(dev);
+    shpc_cleanup(dev, &bridge_dev->bar);
+    memory_region_destroy(&bridge_dev->bar);
+    pci_bridge_exitfn(dev);
+}
+
+static void pci_bridge_dev_write_config(PCIDevice *d,
+                                        uint32_t address, uint32_t val, int len)
+{
+    pci_bridge_write_config(d, address, val, len);
+    if (msi_present(d)) {
+        msi_write_config(d, address, val, len);
+    }
+    shpc_cap_write_config(d, address, val, len);
+}
+
+static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
+{
+    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+
+    pci_bridge_reset(qdev);
+    shpc_reset(dev);
+}
+
+static Property pci_bridge_dev_properties[] = {
+                    /* Note: 0 is not a legal chassis number. */
+    DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0),
+    DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription pci_bridge_dev_vmstate = {
+    .name = "pci_bridge",
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(bridge.dev, PCIBridgeDev),
+        SHPC_VMSTATE(bridge.dev.shpc, PCIBridgeDev),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    k->init = pci_bridge_dev_initfn;
+    k->exit = pci_bridge_dev_exitfn;
+    k->config_write = pci_bridge_dev_write_config;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT;
+    k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE;
+    k->class_id = PCI_CLASS_BRIDGE_PCI;
+    k->is_bridge = 1,
+    dc->desc = "Standard PCI Bridge";
+    dc->reset = qdev_pci_bridge_dev_reset;
+    dc->props = pci_bridge_dev_properties;
+    dc->vmsd = &pci_bridge_dev_vmstate;
+}
+
+static const TypeInfo pci_bridge_dev_info = {
+    .name = "pci-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIBridgeDev),
+    .class_init = pci_bridge_dev_class_init,
+};
+
+static void pci_bridge_dev_register(void)
+{
+    type_register_static(&pci_bridge_dev_info);
+}
+
+type_init(pci_bridge_dev_register);
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
new file mode 100644 (file)
index 0000000..b868f56
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * x3130_downstream.c
+ * TI X3130 pci express downstream port switch
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_downstream.h"
+
+#define PCI_DEVICE_ID_TI_XIO3130D       0x8233  /* downstream port */
+#define XIO3130_REVISION                0x1
+#define XIO3130_MSI_OFFSET              0x70
+#define XIO3130_MSI_SUPPORTED_FLAGS     PCI_MSI_FLAGS_64BIT
+#define XIO3130_MSI_NR_VECTOR           1
+#define XIO3130_SSVID_OFFSET            0x80
+#define XIO3130_SSVID_SVID              0
+#define XIO3130_SSVID_SSID              0
+#define XIO3130_EXP_OFFSET              0x90
+#define XIO3130_AER_OFFSET              0x100
+
+static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
+                                         uint32_t val, int len)
+{
+    pci_bridge_write_config(d, address, val, len);
+    pcie_cap_flr_write_config(d, address, val, len);
+    pcie_cap_slot_write_config(d, address, val, len);
+    pcie_aer_write_config(d, address, val, len);
+}
+
+static void xio3130_downstream_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+
+    pcie_cap_deverr_reset(d);
+    pcie_cap_slot_reset(d);
+    pcie_cap_ari_reset(d);
+    pci_bridge_reset(qdev);
+}
+
+static int xio3130_downstream_initfn(PCIDevice *d)
+{
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+    int rc;
+
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
+    if (rc < 0) {
+        return rc;
+    }
+
+    pcie_port_init_reg(d);
+
+    rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
+                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
+                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
+                               XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
+                       p->port);
+    if (rc < 0) {
+        goto err_msi;
+    }
+    pcie_cap_flr_init(d);
+    pcie_cap_deverr_init(d);
+    pcie_cap_slot_init(d, s->slot);
+    pcie_chassis_create(s->chassis);
+    rc = pcie_chassis_add_slot(s);
+    if (rc < 0) {
+        goto err_pcie_cap;
+    }
+    pcie_cap_ari_init(d);
+    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    pcie_chassis_del_slot(s);
+err_pcie_cap:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    pci_bridge_exitfn(d);
+    return rc;
+}
+
+static void xio3130_downstream_exitfn(PCIDevice *d)
+{
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+
+    pcie_aer_exit(d);
+    pcie_chassis_del_slot(s);
+    pcie_cap_exit(d);
+    msi_uninit(d);
+    pci_bridge_exitfn(d);
+}
+
+PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
+                                  const char *bus_name, pci_map_irq_fn map_irq,
+                                  uint8_t port, uint8_t chassis,
+                                  uint16_t slot)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, multifunction,
+                                 "xio3130-downstream");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+
+    qdev = &br->dev.qdev;
+    pci_bridge_map_irq(br, bus_name, map_irq);
+    qdev_prop_set_uint8(qdev, "port", port);
+    qdev_prop_set_uint8(qdev, "chassis", chassis);
+    qdev_prop_set_uint16(qdev, "slot", slot);
+    qdev_init_nofail(qdev);
+
+    return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
+}
+
+static const VMStateDescription vmstate_xio3130_downstream = {
+    .name = "xio3130-express-downstream-port",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = pcie_cap_slot_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
+        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
+                       vmstate_pcie_aer_log, PCIEAERLog),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property xio3130_downstream_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
+    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
+    port.br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = xio3130_downstream_write_config;
+    k->init = xio3130_downstream_initfn;
+    k->exit = xio3130_downstream_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_TI;
+    k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
+    k->revision = XIO3130_REVISION;
+    dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
+    dc->reset = xio3130_downstream_reset;
+    dc->vmsd = &vmstate_xio3130_downstream;
+    dc->props = xio3130_downstream_properties;
+}
+
+static const TypeInfo xio3130_downstream_info = {
+    .name          = "xio3130-downstream",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIESlot),
+    .class_init    = xio3130_downstream_class_init,
+};
+
+static void xio3130_downstream_register_types(void)
+{
+    type_register_static(&xio3130_downstream_info);
+}
+
+type_init(xio3130_downstream_register_types)
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
new file mode 100644 (file)
index 0000000..cd5d97d
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * xio3130_upstream.c
+ * TI X3130 pci express upstream port switch
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ */
+
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_upstream.h"
+
+#define PCI_DEVICE_ID_TI_XIO3130U       0x8232  /* upstream port */
+#define XIO3130_REVISION                0x2
+#define XIO3130_MSI_OFFSET              0x70
+#define XIO3130_MSI_SUPPORTED_FLAGS     PCI_MSI_FLAGS_64BIT
+#define XIO3130_MSI_NR_VECTOR           1
+#define XIO3130_SSVID_OFFSET            0x80
+#define XIO3130_SSVID_SVID              0
+#define XIO3130_SSVID_SSID              0
+#define XIO3130_EXP_OFFSET              0x90
+#define XIO3130_AER_OFFSET              0x100
+
+static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address,
+                                          uint32_t val, int len)
+{
+    pci_bridge_write_config(d, address, val, len);
+    pcie_cap_flr_write_config(d, address, val, len);
+    pcie_aer_write_config(d, address, val, len);
+}
+
+static void xio3130_upstream_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+
+    pci_bridge_reset(qdev);
+    pcie_cap_deverr_reset(d);
+}
+
+static int xio3130_upstream_initfn(PCIDevice *d)
+{
+    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
+    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+    int rc;
+
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
+    if (rc < 0) {
+        return rc;
+    }
+
+    pcie_port_init_reg(d);
+
+    rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
+                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
+                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
+                               XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
+    if (rc < 0) {
+        goto err_bridge;
+    }
+    rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
+                       p->port);
+    if (rc < 0) {
+        goto err_msi;
+    }
+    pcie_cap_flr_init(d);
+    pcie_cap_deverr_init(d);
+    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
+    if (rc < 0) {
+        goto err;
+    }
+
+    return 0;
+
+err:
+    pcie_cap_exit(d);
+err_msi:
+    msi_uninit(d);
+err_bridge:
+    pci_bridge_exitfn(d);
+    return rc;
+}
+
+static void xio3130_upstream_exitfn(PCIDevice *d)
+{
+    pcie_aer_exit(d);
+    pcie_cap_exit(d);
+    msi_uninit(d);
+    pci_bridge_exitfn(d);
+}
+
+PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
+                             const char *bus_name, pci_map_irq_fn map_irq,
+                             uint8_t port)
+{
+    PCIDevice *d;
+    PCIBridge *br;
+    DeviceState *qdev;
+
+    d = pci_create_multifunction(bus, devfn, multifunction, "x3130-upstream");
+    if (!d) {
+        return NULL;
+    }
+    br = DO_UPCAST(PCIBridge, dev, d);
+
+    qdev = &br->dev.qdev;
+    pci_bridge_map_irq(br, bus_name, map_irq);
+    qdev_prop_set_uint8(qdev, "port", port);
+    qdev_init_nofail(qdev);
+
+    return DO_UPCAST(PCIEPort, br, br);
+}
+
+static const VMStateDescription vmstate_xio3130_upstream = {
+    .name = "xio3130-express-upstream-port",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCIE_DEVICE(br.dev, PCIEPort),
+        VMSTATE_STRUCT(br.dev.exp.aer_log, PCIEPort, 0, vmstate_pcie_aer_log,
+                       PCIEAERLog),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property xio3130_upstream_properties[] = {
+    DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
+    DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
+    PCIE_AER_LOG_MAX_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->is_express = 1;
+    k->is_bridge = 1;
+    k->config_write = xio3130_upstream_write_config;
+    k->init = xio3130_upstream_initfn;
+    k->exit = xio3130_upstream_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_TI;
+    k->device_id = PCI_DEVICE_ID_TI_XIO3130U;
+    k->revision = XIO3130_REVISION;
+    dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
+    dc->reset = xio3130_upstream_reset;
+    dc->vmsd = &vmstate_xio3130_upstream;
+    dc->props = xio3130_upstream_properties;
+}
+
+static const TypeInfo xio3130_upstream_info = {
+    .name          = "x3130-upstream",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIEPort),
+    .class_init    = xio3130_upstream_class_init,
+};
+
+static void xio3130_upstream_register_types(void)
+{
+    type_register_static(&xio3130_upstream_info);
+}
+
+type_init(xio3130_upstream_register_types)
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
new file mode 100644 (file)
index 0000000..909e702
--- /dev/null
@@ -0,0 +1,18 @@
+common-obj-y += pam.o
+
+# PPC devices
+common-obj-$(CONFIG_PREP_PCI) += prep.o
+common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
+# NewWorld PowerMac
+common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
+common-obj-$(CONFIG_DEC_PCI) += dec.o
+# PowerPC E500 boards
+common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o
+
+# ARM devices
+common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
+
+common-obj-$(CONFIG_PCI_APB) += apb.o
+common-obj-$(CONFIG_FULONG) += bonito.o
+common-obj-$(CONFIG_PCI_PIIX) += piix.o
+common-obj-$(CONFIG_PCI_Q35) += q35.o
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
new file mode 100644 (file)
index 0000000..b4981d7
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * QEMU Ultrasparc APB PCI host
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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.
+ */
+
+/* XXX This file and most of its contents are somewhat misnamed.  The
+   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
+   the secondary PCI bridge.  */
+
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci-host/apb.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+/* debug APB */
+//#define DEBUG_APB
+
+#ifdef DEBUG_APB
+#define APB_DPRINTF(fmt, ...) \
+do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define APB_DPRINTF(fmt, ...)
+#endif
+
+/*
+ * Chipset docs:
+ * PBM: "UltraSPARC IIi User's Manual",
+ * http://www.sun.com/processors/manuals/805-0087.pdf
+ *
+ * APB: "Advanced PCI Bridge (APB) User's Manual",
+ * http://www.sun.com/processors/manuals/805-1251.pdf
+ */
+
+#define PBM_PCI_IMR_MASK    0x7fffffff
+#define PBM_PCI_IMR_ENABLED 0x80000000
+
+#define POR          (1 << 31)
+#define SOFT_POR     (1 << 30)
+#define SOFT_XIR     (1 << 29)
+#define BTN_POR      (1 << 28)
+#define BTN_XIR      (1 << 27)
+#define RESET_MASK   0xf8000000
+#define RESET_WCMASK 0x98000000
+#define RESET_WMASK  0x60000000
+
+#define MAX_IVEC 0x30
+
+typedef struct APBState {
+    SysBusDevice busdev;
+    PCIBus      *bus;
+    MemoryRegion apb_config;
+    MemoryRegion pci_config;
+    MemoryRegion pci_mmio;
+    MemoryRegion pci_ioport;
+    uint32_t iommu[4];
+    uint32_t pci_control[16];
+    uint32_t pci_irq_map[8];
+    uint32_t obio_irq_map[32];
+    qemu_irq *pbm_irqs;
+    qemu_irq *ivec_irqs;
+    uint32_t reset_control;
+    unsigned int nr_resets;
+} APBState;
+
+static void pci_apb_set_irq(void *opaque, int irq_num, int level);
+
+static void apb_config_writel (void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    APBState *s = opaque;
+
+    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
+
+    switch (addr & 0xffff) {
+    case 0x30 ... 0x4f: /* DMA error registers */
+        /* XXX: not implemented yet */
+        break;
+    case 0x200 ... 0x20b: /* IOMMU */
+        s->iommu[(addr & 0xf) >> 2] = val;
+        break;
+    case 0x20c ... 0x3ff: /* IOMMU flush */
+        break;
+    case 0xc00 ... 0xc3f: /* PCI interrupt control */
+        if (addr & 4) {
+            s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
+            s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+        }
+        break;
+    case 0x1000 ... 0x1080: /* OBIO interrupt control */
+        if (addr & 4) {
+            s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
+            s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+        }
+        break;
+    case 0x1400 ... 0x143f: /* PCI interrupt clear */
+        if (addr & 4) {
+            pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0);
+        }
+        break;
+    case 0x1800 ... 0x1860: /* OBIO interrupt clear */
+        if (addr & 4) {
+            pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0);
+        }
+        break;
+    case 0x2000 ... 0x202f: /* PCI control */
+        s->pci_control[(addr & 0x3f) >> 2] = val;
+        break;
+    case 0xf020 ... 0xf027: /* Reset control */
+        if (addr & 4) {
+            val &= RESET_MASK;
+            s->reset_control &= ~(val & RESET_WCMASK);
+            s->reset_control |= val & RESET_WMASK;
+            if (val & SOFT_POR) {
+                s->nr_resets = 0;
+                qemu_system_reset_request();
+            } else if (val & SOFT_XIR) {
+                qemu_system_reset_request();
+            }
+        }
+        break;
+    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
+    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
+    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
+    case 0xf000 ... 0xf01f: /* FFB config, memory control */
+        /* we don't care */
+    default:
+        break;
+    }
+}
+
+static uint64_t apb_config_readl (void *opaque,
+                                  hwaddr addr, unsigned size)
+{
+    APBState *s = opaque;
+    uint32_t val;
+
+    switch (addr & 0xffff) {
+    case 0x30 ... 0x4f: /* DMA error registers */
+        val = 0;
+        /* XXX: not implemented yet */
+        break;
+    case 0x200 ... 0x20b: /* IOMMU */
+        val = s->iommu[(addr & 0xf) >> 2];
+        break;
+    case 0x20c ... 0x3ff: /* IOMMU flush */
+        val = 0;
+        break;
+    case 0xc00 ... 0xc3f: /* PCI interrupt control */
+        if (addr & 4) {
+            val = s->pci_irq_map[(addr & 0x3f) >> 3];
+        } else {
+            val = 0;
+        }
+        break;
+    case 0x1000 ... 0x1080: /* OBIO interrupt control */
+        if (addr & 4) {
+            val = s->obio_irq_map[(addr & 0xff) >> 3];
+        } else {
+            val = 0;
+        }
+        break;
+    case 0x2000 ... 0x202f: /* PCI control */
+        val = s->pci_control[(addr & 0x3f) >> 2];
+        break;
+    case 0xf020 ... 0xf027: /* Reset control */
+        if (addr & 4) {
+            val = s->reset_control;
+        } else {
+            val = 0;
+        }
+        break;
+    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
+    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
+    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
+    case 0xf000 ... 0xf01f: /* FFB config, memory control */
+        /* we don't care */
+    default:
+        val = 0;
+        break;
+    }
+    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
+
+    return val;
+}
+
+static const MemoryRegionOps apb_config_ops = {
+    .read = apb_config_readl,
+    .write = apb_config_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void apb_pci_config_write(void *opaque, hwaddr addr,
+                                 uint64_t val, unsigned size)
+{
+    APBState *s = opaque;
+
+    val = qemu_bswap_len(val, size);
+    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
+    pci_data_write(s->bus, addr, val, size);
+}
+
+static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    uint32_t ret;
+    APBState *s = opaque;
+
+    ret = pci_data_read(s->bus, addr, size);
+    ret = qemu_bswap_len(ret, size);
+    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
+    return ret;
+}
+
+static void pci_apb_iowriteb (void *opaque, hwaddr addr,
+                                  uint32_t val)
+{
+    cpu_outb(addr & IOPORTS_MASK, val);
+}
+
+static void pci_apb_iowritew (void *opaque, hwaddr addr,
+                                  uint32_t val)
+{
+    cpu_outw(addr & IOPORTS_MASK, bswap16(val));
+}
+
+static void pci_apb_iowritel (void *opaque, hwaddr addr,
+                                uint32_t val)
+{
+    cpu_outl(addr & IOPORTS_MASK, bswap32(val));
+}
+
+static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
+{
+    uint32_t val;
+
+    val = cpu_inb(addr & IOPORTS_MASK);
+    return val;
+}
+
+static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
+{
+    uint32_t val;
+
+    val = bswap16(cpu_inw(addr & IOPORTS_MASK));
+    return val;
+}
+
+static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
+{
+    uint32_t val;
+
+    val = bswap32(cpu_inl(addr & IOPORTS_MASK));
+    return val;
+}
+
+static const MemoryRegionOps pci_ioport_ops = {
+    .old_mmio = {
+        .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
+        .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* The APB host has an IRQ line for each IRQ line of each slot.  */
+static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
+}
+
+static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int bus_offset;
+    if (pci_dev->devfn & 1)
+        bus_offset = 16;
+    else
+        bus_offset = 0;
+    return bus_offset + irq_num;
+}
+
+static void pci_apb_set_irq(void *opaque, int irq_num, int level)
+{
+    APBState *s = opaque;
+
+    /* PCI IRQ map onto the first 32 INO.  */
+    if (irq_num < 32) {
+        if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
+            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
+            qemu_set_irq(s->ivec_irqs[irq_num], level);
+        } else {
+            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
+            qemu_irq_lower(s->ivec_irqs[irq_num]);
+        }
+    } else {
+        /* OBIO IRQ map onto the next 16 INO.  */
+        if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
+            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
+            qemu_set_irq(s->ivec_irqs[irq_num], level);
+        } else {
+            APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
+            qemu_irq_lower(s->ivec_irqs[irq_num]);
+        }
+    }
+}
+
+static int apb_pci_bridge_initfn(PCIDevice *dev)
+{
+    int rc;
+
+    rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
+    if (rc < 0) {
+        return rc;
+    }
+
+    /*
+     * command register:
+     * According to PCI bridge spec, after reset
+     *   bus master bit is off
+     *   memory space enable bit is off
+     * According to manual (805-1251.pdf).
+     *   the reset value should be zero unless the boot pin is tied high
+     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
+     */
+    pci_set_word(dev->config + PCI_COMMAND,
+                 PCI_COMMAND_MEMORY);
+    pci_set_word(dev->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
+                 PCI_STATUS_DEVSEL_MEDIUM);
+    return 0;
+}
+
+PCIBus *pci_apb_init(hwaddr special_base,
+                     hwaddr mem_base,
+                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
+                     qemu_irq **pbm_irqs)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    APBState *d;
+    PCIDevice *pci_dev;
+    PCIBridge *br;
+
+    /* Ultrasparc PBM main bus */
+    dev = qdev_create(NULL, "pbm");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    /* apb_config */
+    sysbus_mmio_map(s, 0, special_base);
+    /* PCI configuration space */
+    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
+    /* pci_ioport */
+    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
+    d = FROM_SYSBUS(APBState, s);
+
+    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
+    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
+
+    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
+                              pci_apb_set_irq, pci_pbm_map_irq, d,
+                              &d->pci_mmio,
+                              get_system_io(),
+                              0, 32, TYPE_PCI_BUS);
+
+    *pbm_irqs = d->pbm_irqs;
+    d->ivec_irqs = ivec_irqs;
+
+    pci_create_simple(d->bus, 0, "pbm-pci");
+
+    /* APB secondary busses */
+    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
+                                   "pbm-bridge");
+    br = DO_UPCAST(PCIBridge, dev, pci_dev);
+    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
+                       pci_apb_map_irq);
+    qdev_init_nofail(&pci_dev->qdev);
+    *bus2 = pci_bridge_get_sec_bus(br);
+
+    pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
+                                   "pbm-bridge");
+    br = DO_UPCAST(PCIBridge, dev, pci_dev);
+    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
+                       pci_apb_map_irq);
+    qdev_init_nofail(&pci_dev->qdev);
+    *bus3 = pci_bridge_get_sec_bus(br);
+
+    return d->bus;
+}
+
+static void pci_pbm_reset(DeviceState *d)
+{
+    unsigned int i;
+    APBState *s = container_of(d, APBState, busdev.qdev);
+
+    for (i = 0; i < 8; i++) {
+        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
+    }
+    for (i = 0; i < 32; i++) {
+        s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
+    }
+
+    if (s->nr_resets++ == 0) {
+        /* Power on reset */
+        s->reset_control = POR;
+    }
+}
+
+static const MemoryRegionOps pci_config_ops = {
+    .read = apb_pci_config_read,
+    .write = apb_pci_config_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pci_pbm_init_device(SysBusDevice *dev)
+{
+    APBState *s;
+    unsigned int i;
+
+    s = FROM_SYSBUS(APBState, dev);
+    for (i = 0; i < 8; i++) {
+        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
+    }
+    for (i = 0; i < 32; i++) {
+        s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
+    }
+    s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
+
+    /* apb_config */
+    memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
+                          0x10000);
+    /* at region 0 */
+    sysbus_init_mmio(dev, &s->apb_config);
+
+    memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
+                          0x1000000);
+    /* at region 1 */
+    sysbus_init_mmio(dev, &s->pci_config);
+
+    /* pci_ioport */
+    memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
+                          "apb-pci-ioport", 0x10000);
+    /* at region 2 */
+    sysbus_init_mmio(dev, &s->pci_ioport);
+
+    return 0;
+}
+
+static int pbm_pci_host_init(PCIDevice *d)
+{
+    pci_set_word(d->config + PCI_COMMAND,
+                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+    pci_set_word(d->config + PCI_STATUS,
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
+                 PCI_STATUS_DEVSEL_MEDIUM);
+    return 0;
+}
+
+static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pbm_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo pbm_pci_host_info = {
+    .name          = "pbm-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = pbm_pci_host_class_init,
+};
+
+static void pbm_host_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pci_pbm_init_device;
+    dc->reset = pci_pbm_reset;
+}
+
+static const TypeInfo pbm_host_info = {
+    .name          = "pbm",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(APBState),
+    .class_init    = pbm_host_class_init,
+};
+
+static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = apb_pci_bridge_initfn;
+    k->exit = pci_bridge_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
+    k->revision = 0x11;
+    k->config_write = pci_bridge_write_config;
+    k->is_bridge = 1;
+    dc->reset = pci_bridge_reset;
+    dc->vmsd = &vmstate_pci_device;
+}
+
+static const TypeInfo pbm_pci_bridge_info = {
+    .name          = "pbm-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIBridge),
+    .class_init    = pbm_pci_bridge_class_init,
+};
+
+static void pbm_register_types(void)
+{
+    type_register_static(&pbm_host_info);
+    type_register_static(&pbm_pci_host_info);
+    type_register_static(&pbm_pci_bridge_info);
+}
+
+type_init(pbm_register_types)
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
new file mode 100644 (file)
index 0000000..974150b
--- /dev/null
@@ -0,0 +1,847 @@
+/*
+ * bonito north bridge support
+ *
+ * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
+ * Copyright (c) 2010 Huacai Chen (zltjiangshi@gmail.com)
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+/*
+ * fulong 2e mini pc has a bonito north bridge.
+ */
+
+/* what is the meaning of devfn in qemu and IDSEL in bonito northbridge?
+ *
+ * devfn   pci_slot<<3  + funno
+ * one pci bus can have 32 devices and each device can have 8 functions.
+ *
+ * In bonito north bridge, pci slot = IDSEL bit - 12.
+ * For example, PCI_IDSEL_VIA686B = 17,
+ * pci slot = 17-12=5
+ *
+ * so
+ * VT686B_FUN0's devfn = (5<<3)+0
+ * VT686B_FUN1's devfn = (5<<3)+1
+ *
+ * qemu also uses pci address for north bridge to access pci config register.
+ * bus_no   [23:16]
+ * dev_no   [15:11]
+ * fun_no   [10:8]
+ * reg_no   [7:2]
+ *
+ * so function bonito_sbridge_pciaddr for the translation from
+ * north bridge address to pci address.
+ */
+
+#include <assert.h>
+
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/i386/pc.h"
+#include "hw/mips/mips.h"
+#include "hw/pci/pci_host.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_BONITO
+
+#ifdef DEBUG_BONITO
+#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+/* from linux soure code. include/asm-mips/mips-boards/bonito64.h*/
+#define BONITO_BOOT_BASE        0x1fc00000
+#define BONITO_BOOT_SIZE        0x00100000
+#define BONITO_BOOT_TOP         (BONITO_BOOT_BASE+BONITO_BOOT_SIZE-1)
+#define BONITO_FLASH_BASE       0x1c000000
+#define BONITO_FLASH_SIZE       0x03000000
+#define BONITO_FLASH_TOP        (BONITO_FLASH_BASE+BONITO_FLASH_SIZE-1)
+#define BONITO_SOCKET_BASE      0x1f800000
+#define BONITO_SOCKET_SIZE      0x00400000
+#define BONITO_SOCKET_TOP       (BONITO_SOCKET_BASE+BONITO_SOCKET_SIZE-1)
+#define BONITO_REG_BASE         0x1fe00000
+#define BONITO_REG_SIZE         0x00040000
+#define BONITO_REG_TOP          (BONITO_REG_BASE+BONITO_REG_SIZE-1)
+#define BONITO_DEV_BASE         0x1ff00000
+#define BONITO_DEV_SIZE         0x00100000
+#define BONITO_DEV_TOP          (BONITO_DEV_BASE+BONITO_DEV_SIZE-1)
+#define BONITO_PCILO_BASE       0x10000000
+#define BONITO_PCILO_BASE_VA    0xb0000000
+#define BONITO_PCILO_SIZE       0x0c000000
+#define BONITO_PCILO_TOP        (BONITO_PCILO_BASE+BONITO_PCILO_SIZE-1)
+#define BONITO_PCILO0_BASE      0x10000000
+#define BONITO_PCILO1_BASE      0x14000000
+#define BONITO_PCILO2_BASE      0x18000000
+#define BONITO_PCIHI_BASE       0x20000000
+#define BONITO_PCIHI_SIZE       0x20000000
+#define BONITO_PCIHI_TOP        (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1)
+#define BONITO_PCIIO_BASE       0x1fd00000
+#define BONITO_PCIIO_BASE_VA    0xbfd00000
+#define BONITO_PCIIO_SIZE       0x00010000
+#define BONITO_PCIIO_TOP        (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1)
+#define BONITO_PCICFG_BASE      0x1fe80000
+#define BONITO_PCICFG_SIZE      0x00080000
+#define BONITO_PCICFG_TOP       (BONITO_PCICFG_BASE+BONITO_PCICFG_SIZE-1)
+
+
+#define BONITO_PCICONFIGBASE    0x00
+#define BONITO_REGBASE          0x100
+
+#define BONITO_PCICONFIG_BASE   (BONITO_PCICONFIGBASE+BONITO_REG_BASE)
+#define BONITO_PCICONFIG_SIZE   (0x100)
+
+#define BONITO_INTERNAL_REG_BASE  (BONITO_REGBASE+BONITO_REG_BASE)
+#define BONITO_INTERNAL_REG_SIZE  (0x70)
+
+#define BONITO_SPCICONFIG_BASE  (BONITO_PCICFG_BASE)
+#define BONITO_SPCICONFIG_SIZE  (BONITO_PCICFG_SIZE)
+
+
+
+/* 1. Bonito h/w Configuration */
+/* Power on register */
+
+#define BONITO_BONPONCFG        (0x00 >> 2)      /* 0x100 */
+#define BONITO_BONGENCFG_OFFSET 0x4
+#define BONITO_BONGENCFG        (BONITO_BONGENCFG_OFFSET>>2)   /*0x104 */
+
+/* 2. IO & IDE configuration */
+#define BONITO_IODEVCFG         (0x08 >> 2)      /* 0x108 */
+
+/* 3. IO & IDE configuration */
+#define BONITO_SDCFG            (0x0c >> 2)      /* 0x10c */
+
+/* 4. PCI address map control */
+#define BONITO_PCIMAP           (0x10 >> 2)      /* 0x110 */
+#define BONITO_PCIMEMBASECFG    (0x14 >> 2)      /* 0x114 */
+#define BONITO_PCIMAP_CFG       (0x18 >> 2)      /* 0x118 */
+
+/* 5. ICU & GPIO regs */
+/* GPIO Regs - r/w */
+#define BONITO_GPIODATA_OFFSET  0x1c
+#define BONITO_GPIODATA         (BONITO_GPIODATA_OFFSET >> 2)   /* 0x11c */
+#define BONITO_GPIOIE           (0x20 >> 2)      /* 0x120 */
+
+/* ICU Configuration Regs - r/w */
+#define BONITO_INTEDGE          (0x24 >> 2)      /* 0x124 */
+#define BONITO_INTSTEER         (0x28 >> 2)      /* 0x128 */
+#define BONITO_INTPOL           (0x2c >> 2)      /* 0x12c */
+
+/* ICU Enable Regs - IntEn & IntISR are r/o. */
+#define BONITO_INTENSET         (0x30 >> 2)      /* 0x130 */
+#define BONITO_INTENCLR         (0x34 >> 2)      /* 0x134 */
+#define BONITO_INTEN            (0x38 >> 2)      /* 0x138 */
+#define BONITO_INTISR           (0x3c >> 2)      /* 0x13c */
+
+/* PCI mail boxes */
+#define BONITO_PCIMAIL0_OFFSET    0x40
+#define BONITO_PCIMAIL1_OFFSET    0x44
+#define BONITO_PCIMAIL2_OFFSET    0x48
+#define BONITO_PCIMAIL3_OFFSET    0x4c
+#define BONITO_PCIMAIL0         (0x40 >> 2)      /* 0x140 */
+#define BONITO_PCIMAIL1         (0x44 >> 2)      /* 0x144 */
+#define BONITO_PCIMAIL2         (0x48 >> 2)      /* 0x148 */
+#define BONITO_PCIMAIL3         (0x4c >> 2)      /* 0x14c */
+
+/* 6. PCI cache */
+#define BONITO_PCICACHECTRL     (0x50 >> 2)      /* 0x150 */
+#define BONITO_PCICACHETAG      (0x54 >> 2)      /* 0x154 */
+#define BONITO_PCIBADADDR       (0x58 >> 2)      /* 0x158 */
+#define BONITO_PCIMSTAT         (0x5c >> 2)      /* 0x15c */
+
+/* 7. other*/
+#define BONITO_TIMECFG          (0x60 >> 2)      /* 0x160 */
+#define BONITO_CPUCFG           (0x64 >> 2)      /* 0x164 */
+#define BONITO_DQCFG            (0x68 >> 2)      /* 0x168 */
+#define BONITO_MEMSIZE          (0x6C >> 2)      /* 0x16c */
+
+#define BONITO_REGS             (0x70 >> 2)
+
+/* PCI config for south bridge. type 0 */
+#define BONITO_PCICONF_IDSEL_MASK      0xfffff800     /* [31:11] */
+#define BONITO_PCICONF_IDSEL_OFFSET    11
+#define BONITO_PCICONF_FUN_MASK        0x700    /* [10:8] */
+#define BONITO_PCICONF_FUN_OFFSET      8
+#define BONITO_PCICONF_REG_MASK        0xFC
+#define BONITO_PCICONF_REG_OFFSET      0
+
+
+/* idsel BIT = pci slot number +12 */
+#define PCI_SLOT_BASE              12
+#define PCI_IDSEL_VIA686B_BIT      (17)
+#define PCI_IDSEL_VIA686B          (1<<PCI_IDSEL_VIA686B_BIT)
+
+#define PCI_ADDR(busno,devno,funno,regno)  \
+    ((((busno)<<16)&0xff0000) + (((devno)<<11)&0xf800) + (((funno)<<8)&0x700) + (regno))
+
+#define TYPE_BONITO_PCI_HOST_BRIDGE "Bonito-pcihost"
+
+typedef struct BonitoState BonitoState;
+
+typedef struct PCIBonitoState
+{
+    PCIDevice dev;
+
+    BonitoState *pcihost;
+    uint32_t regs[BONITO_REGS];
+
+    struct bonldma {
+        uint32_t ldmactrl;
+        uint32_t ldmastat;
+        uint32_t ldmaaddr;
+        uint32_t ldmago;
+    } bonldma;
+
+    /* Based at 1fe00300, bonito Copier */
+    struct boncop {
+        uint32_t copctrl;
+        uint32_t copstat;
+        uint32_t coppaddr;
+        uint32_t copgo;
+    } boncop;
+
+    /* Bonito registers */
+    MemoryRegion iomem;
+    MemoryRegion iomem_ldma;
+    MemoryRegion iomem_cop;
+
+    hwaddr bonito_pciio_start;
+    hwaddr bonito_pciio_length;
+    int bonito_pciio_handle;
+
+    hwaddr bonito_localio_start;
+    hwaddr bonito_localio_length;
+    int bonito_localio_handle;
+
+} PCIBonitoState;
+
+#define BONITO_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(BonitoState, (obj), TYPE_BONITO_PCI_HOST_BRIDGE)
+
+struct BonitoState {
+    PCIHostState parent_obj;
+
+    qemu_irq *pic;
+
+    PCIBonitoState *pci_dev;
+};
+
+static void bonito_writel(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned size)
+{
+    PCIBonitoState *s = opaque;
+    uint32_t saddr;
+    int reset = 0;
+
+    saddr = (addr - BONITO_REGBASE) >> 2;
+
+    DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n", addr, val, saddr);
+    switch (saddr) {
+    case BONITO_BONPONCFG:
+    case BONITO_IODEVCFG:
+    case BONITO_SDCFG:
+    case BONITO_PCIMAP:
+    case BONITO_PCIMEMBASECFG:
+    case BONITO_PCIMAP_CFG:
+    case BONITO_GPIODATA:
+    case BONITO_GPIOIE:
+    case BONITO_INTEDGE:
+    case BONITO_INTSTEER:
+    case BONITO_INTPOL:
+    case BONITO_PCIMAIL0:
+    case BONITO_PCIMAIL1:
+    case BONITO_PCIMAIL2:
+    case BONITO_PCIMAIL3:
+    case BONITO_PCICACHECTRL:
+    case BONITO_PCICACHETAG:
+    case BONITO_PCIBADADDR:
+    case BONITO_PCIMSTAT:
+    case BONITO_TIMECFG:
+    case BONITO_CPUCFG:
+    case BONITO_DQCFG:
+    case BONITO_MEMSIZE:
+        s->regs[saddr] = val;
+        break;
+    case BONITO_BONGENCFG:
+        if (!(s->regs[saddr] & 0x04) && (val & 0x04)) {
+            reset = 1; /* bit 2 jump from 0 to 1 cause reset */
+        }
+        s->regs[saddr] = val;
+        if (reset) {
+            qemu_system_reset_request();
+        }
+        break;
+    case BONITO_INTENSET:
+        s->regs[BONITO_INTENSET] = val;
+        s->regs[BONITO_INTEN] |= val;
+        break;
+    case BONITO_INTENCLR:
+        s->regs[BONITO_INTENCLR] = val;
+        s->regs[BONITO_INTEN] &= ~val;
+        break;
+    case BONITO_INTEN:
+    case BONITO_INTISR:
+        DPRINTF("write to readonly bonito register %x\n", saddr);
+        break;
+    default:
+        DPRINTF("write to unknown bonito register %x\n", saddr);
+        break;
+    }
+}
+
+static uint64_t bonito_readl(void *opaque, hwaddr addr,
+                             unsigned size)
+{
+    PCIBonitoState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr - BONITO_REGBASE) >> 2;
+
+    DPRINTF("bonito_readl "TARGET_FMT_plx"\n", addr);
+    switch (saddr) {
+    case BONITO_INTISR:
+        return s->regs[saddr];
+    default:
+        return s->regs[saddr];
+    }
+}
+
+static const MemoryRegionOps bonito_ops = {
+    .read = bonito_readl,
+    .write = bonito_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void bonito_pciconf_writel(void *opaque, hwaddr addr,
+                                  uint64_t val, unsigned size)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+
+    DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
+    d->config_write(d, addr, val, 4);
+}
+
+static uint64_t bonito_pciconf_readl(void *opaque, hwaddr addr,
+                                     unsigned size)
+{
+
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+
+    DPRINTF("bonito_pciconf_readl "TARGET_FMT_plx"\n", addr);
+    return d->config_read(d, addr, 4);
+}
+
+/* north bridge PCI configure space. 0x1fe0 0000 - 0x1fe0 00ff */
+
+static const MemoryRegionOps bonito_pciconf_ops = {
+    .read = bonito_pciconf_readl,
+    .write = bonito_pciconf_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t bonito_ldma_readl(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    uint32_t val;
+    PCIBonitoState *s = opaque;
+
+    val = ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)];
+
+    return val;
+}
+
+static void bonito_ldma_writel(void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    PCIBonitoState *s = opaque;
+
+    ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff;
+}
+
+static const MemoryRegionOps bonito_ldma_ops = {
+    .read = bonito_ldma_readl,
+    .write = bonito_ldma_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t bonito_cop_readl(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    uint32_t val;
+    PCIBonitoState *s = opaque;
+
+    val = ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)];
+
+    return val;
+}
+
+static void bonito_cop_writel(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned size)
+{
+    PCIBonitoState *s = opaque;
+
+    ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff;
+}
+
+static const MemoryRegionOps bonito_cop_ops = {
+    .read = bonito_cop_readl,
+    .write = bonito_cop_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr)
+{
+    PCIBonitoState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t cfgaddr;
+    uint32_t idsel;
+    uint32_t devno;
+    uint32_t funno;
+    uint32_t regno;
+    uint32_t pciaddr;
+
+    /* support type0 pci config */
+    if ((s->regs[BONITO_PCIMAP_CFG] & 0x10000) != 0x0) {
+        return 0xffffffff;
+    }
+
+    cfgaddr = addr & 0xffff;
+    cfgaddr |= (s->regs[BONITO_PCIMAP_CFG] & 0xffff) << 16;
+
+    idsel = (cfgaddr & BONITO_PCICONF_IDSEL_MASK) >> BONITO_PCICONF_IDSEL_OFFSET;
+    devno = ffs(idsel) - 1;
+    funno = (cfgaddr & BONITO_PCICONF_FUN_MASK) >> BONITO_PCICONF_FUN_OFFSET;
+    regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET;
+
+    if (idsel == 0) {
+        fprintf(stderr, "error in bonito pci config address " TARGET_FMT_plx
+            ",pcimap_cfg=%x\n", addr, s->regs[BONITO_PCIMAP_CFG]);
+        exit(1);
+    }
+    pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno);
+    DPRINTF("cfgaddr %x pciaddr %x busno %x devno %d funno %d regno %d\n",
+        cfgaddr, pciaddr, pci_bus_num(phb->bus), devno, funno, regno);
+
+    return pciaddr;
+}
+
+static void bonito_spciconf_writeb(void *opaque, hwaddr addr,
+                                   uint32_t val)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_writeb "TARGET_FMT_plx" val %x\n", addr, val);
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val & 0xff, 1);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+}
+
+static void bonito_spciconf_writew(void *opaque, hwaddr addr,
+                                   uint32_t val)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);
+    assert((addr & 0x1) == 0);
+
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val, 2);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+}
+
+static void bonito_spciconf_writel(void *opaque, hwaddr addr,
+                                   uint32_t val)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
+    assert((addr & 0x3) == 0);
+
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+    pci_data_write(phb->bus, phb->config_reg, val, 4);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+}
+
+static uint32_t bonito_spciconf_readb(void *opaque, hwaddr addr)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"\n", addr);
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return 0xff;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+
+    return pci_data_read(phb->bus, phb->config_reg, 1);
+}
+
+static uint32_t bonito_spciconf_readw(void *opaque, hwaddr addr)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr);
+    assert((addr & 0x1) == 0);
+
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return 0xffff;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+
+    return pci_data_read(phb->bus, phb->config_reg, 2);
+}
+
+static uint32_t bonito_spciconf_readl(void *opaque, hwaddr addr)
+{
+    PCIBonitoState *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+    uint32_t pciaddr;
+    uint16_t status;
+
+    DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr);
+    assert((addr & 0x3) == 0);
+
+    pciaddr = bonito_sbridge_pciaddr(s, addr);
+
+    if (pciaddr == 0xffffffff) {
+        return 0xffffffff;
+    }
+
+    /* set the pci address in s->config_reg */
+    phb->config_reg = (pciaddr) | (1u << 31);
+
+    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
+    status = pci_get_word(d->config + PCI_STATUS);
+    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
+    pci_set_word(d->config + PCI_STATUS, status);
+
+    return pci_data_read(phb->bus, phb->config_reg, 4);
+}
+
+/* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
+static const MemoryRegionOps bonito_spciconf_ops = {
+    .old_mmio = {
+        .read = {
+            bonito_spciconf_readb,
+            bonito_spciconf_readw,
+            bonito_spciconf_readl,
+        },
+        .write = {
+            bonito_spciconf_writeb,
+            bonito_spciconf_writew,
+            bonito_spciconf_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define BONITO_IRQ_BASE 32
+
+static void pci_bonito_set_irq(void *opaque, int irq_num, int level)
+{
+    BonitoState *s = opaque;
+    qemu_irq *pic = s->pic;
+    PCIBonitoState *bonito_state = s->pci_dev;
+    int internal_irq = irq_num - BONITO_IRQ_BASE;
+
+    if (bonito_state->regs[BONITO_INTEDGE] & (1 << internal_irq)) {
+        qemu_irq_pulse(*pic);
+    } else {   /* level triggered */
+        if (bonito_state->regs[BONITO_INTPOL] & (1 << internal_irq)) {
+            qemu_irq_raise(*pic);
+        } else {
+            qemu_irq_lower(*pic);
+        }
+    }
+}
+
+/* map the original irq (0~3) to bonito irq (16~47, but 16~31 are unused) */
+static int pci_bonito_map_irq(PCIDevice * pci_dev, int irq_num)
+{
+    int slot;
+
+    slot = (pci_dev->devfn >> 3);
+
+    switch (slot) {
+    case 5:   /* FULONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */
+        return irq_num % 4 + BONITO_IRQ_BASE;
+    case 6:   /* FULONG2E_ATI_SLOT, VGA */
+        return 4 + BONITO_IRQ_BASE;
+    case 7:   /* FULONG2E_RTL_SLOT, RTL8139 */
+        return 5 + BONITO_IRQ_BASE;
+    case 8 ... 12: /* PCI slot 1 to 4 */
+        return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE;
+    default:  /* Unknown device, don't do any translation */
+        return irq_num;
+    }
+}
+
+static void bonito_reset(void *opaque)
+{
+    PCIBonitoState *s = opaque;
+
+    /* set the default value of north bridge registers */
+
+    s->regs[BONITO_BONPONCFG] = 0xc40;
+    s->regs[BONITO_BONGENCFG] = 0x1384;
+    s->regs[BONITO_IODEVCFG] = 0x2bff8010;
+    s->regs[BONITO_SDCFG] = 0x255e0091;
+
+    s->regs[BONITO_GPIODATA] = 0x1ff;
+    s->regs[BONITO_GPIOIE] = 0x1ff;
+    s->regs[BONITO_DQCFG] = 0x8;
+    s->regs[BONITO_MEMSIZE] = 0x10000000;
+    s->regs[BONITO_PCIMAP] = 0x6140;
+}
+
+static const VMStateDescription vmstate_bonito = {
+    .name = "Bonito",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(dev, PCIBonitoState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int bonito_pcihost_initfn(SysBusDevice *dev)
+{
+    PCIHostState *phb = PCI_HOST_BRIDGE(dev);
+
+    phb->bus = pci_register_bus(DEVICE(dev), "pci",
+                                pci_bonito_set_irq, pci_bonito_map_irq, dev,
+                                get_system_memory(), get_system_io(),
+                                0x28, 32, TYPE_PCI_BUS);
+
+    return 0;
+}
+
+static int bonito_initfn(PCIDevice *dev)
+{
+    PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev);
+    SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+
+    /* Bonito North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */
+    pci_config_set_prog_interface(dev->config, 0x00);
+
+    /* set the north bridge register mapping */
+    memory_region_init_io(&s->iomem, &bonito_ops, s,
+                          "north-bridge-register", BONITO_INTERNAL_REG_SIZE);
+    sysbus_init_mmio(sysbus, &s->iomem);
+    sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE);
+
+    /* set the north bridge pci configure  mapping */
+    memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s,
+                          "north-bridge-pci-config", BONITO_PCICONFIG_SIZE);
+    sysbus_init_mmio(sysbus, &phb->conf_mem);
+    sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE);
+
+    /* set the south bridge pci configure  mapping */
+    memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s,
+                          "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE);
+    sysbus_init_mmio(sysbus, &phb->data_mem);
+    sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
+
+    memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s,
+                          "ldma", 0x100);
+    sysbus_init_mmio(sysbus, &s->iomem_ldma);
+    sysbus_mmio_map(sysbus, 3, 0xbfe00200);
+
+    memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s,
+                          "cop", 0x100);
+    sysbus_init_mmio(sysbus, &s->iomem_cop);
+    sysbus_mmio_map(sysbus, 4, 0xbfe00300);
+
+    /* Map PCI IO Space  0x1fd0 0000 - 0x1fd1 0000 */
+    s->bonito_pciio_start = BONITO_PCIIO_BASE;
+    s->bonito_pciio_length = BONITO_PCIIO_SIZE;
+    isa_mem_base = s->bonito_pciio_start;
+    isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length);
+
+    /* add pci local io mapping */
+    s->bonito_localio_start = BONITO_DEV_BASE;
+    s->bonito_localio_length = BONITO_DEV_SIZE;
+    isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length);
+
+    /* set the default value of north bridge pci config */
+    pci_set_word(dev->config + PCI_COMMAND, 0x0000);
+    pci_set_word(dev->config + PCI_STATUS, 0x0000);
+    pci_set_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID, 0x0000);
+    pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x0000);
+
+    pci_set_byte(dev->config + PCI_INTERRUPT_LINE, 0x00);
+    pci_set_byte(dev->config + PCI_INTERRUPT_PIN, 0x01);
+    pci_set_byte(dev->config + PCI_MIN_GNT, 0x3c);
+    pci_set_byte(dev->config + PCI_MAX_LAT, 0x00);
+
+    qemu_register_reset(bonito_reset, s);
+
+    return 0;
+}
+
+PCIBus *bonito_init(qemu_irq *pic)
+{
+    DeviceState *dev;
+    BonitoState *pcihost;
+    PCIHostState *phb;
+    PCIBonitoState *s;
+    PCIDevice *d;
+
+    dev = qdev_create(NULL, TYPE_BONITO_PCI_HOST_BRIDGE);
+    phb = PCI_HOST_BRIDGE(dev);
+    pcihost = BONITO_PCI_HOST_BRIDGE(dev);
+    pcihost->pic = pic;
+    qdev_init_nofail(dev);
+
+    /* set the pcihost pointer before bonito_initfn is called */
+    d = pci_create(phb->bus, PCI_DEVFN(0, 0), "Bonito");
+    s = DO_UPCAST(PCIBonitoState, dev, d);
+    s->pcihost = pcihost;
+    pcihost->pci_dev = s;
+    qdev_init_nofail(DEVICE(d));
+
+    return phb->bus;
+}
+
+static void bonito_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = bonito_initfn;
+    k->vendor_id = 0xdf53;
+    k->device_id = 0x00d5;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    dc->desc = "Host bridge";
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_bonito;
+}
+
+static const TypeInfo bonito_info = {
+    .name          = "Bonito",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIBonitoState),
+    .class_init    = bonito_class_init,
+};
+
+static void bonito_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = bonito_pcihost_initfn;
+    dc->no_user = 1;
+}
+
+static const TypeInfo bonito_pcihost_info = {
+    .name          = TYPE_BONITO_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(BonitoState),
+    .class_init    = bonito_pcihost_class_init,
+};
+
+static void bonito_register_types(void)
+{
+    type_register_static(&bonito_pcihost_info);
+    type_register_static(&bonito_info);
+}
+
+type_init(bonito_register_types)
diff --git a/hw/pci-host/dec.c b/hw/pci-host/dec.c
new file mode 100644 (file)
index 0000000..6ec3d22
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * QEMU DEC 21154 PCI bridge
+ *
+ * Copyright (c) 2006-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/dec_pci.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+
+/* debug DEC */
+//#define DEBUG_DEC
+
+#ifdef DEBUG_DEC
+#define DEC_DPRINTF(fmt, ...)                               \
+    do { printf("DEC: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DEC_DPRINTF(fmt, ...)
+#endif
+
+#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
+
+typedef struct DECState {
+    PCIHostState parent_obj;
+} DECState;
+
+static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return irq_num;
+}
+
+static int dec_pci_bridge_initfn(PCIDevice *pci_dev)
+{
+    return pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
+}
+
+static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = dec_pci_bridge_initfn;
+    k->exit = pci_bridge_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_DEC;
+    k->device_id = PCI_DEVICE_ID_DEC_21154;
+    k->config_write = pci_bridge_write_config;
+    k->is_bridge = 1;
+    dc->desc = "DEC 21154 PCI-PCI bridge";
+    dc->reset = pci_bridge_reset;
+    dc->vmsd = &vmstate_pci_device;
+}
+
+static const TypeInfo dec_21154_pci_bridge_info = {
+    .name          = "dec-21154-p2p-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIBridge),
+    .class_init    = dec_21154_pci_bridge_class_init,
+};
+
+PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
+{
+    PCIDevice *dev;
+    PCIBridge *br;
+
+    dev = pci_create_multifunction(parent_bus, devfn, false,
+                                   "dec-21154-p2p-bridge");
+    br = DO_UPCAST(PCIBridge, dev, dev);
+    pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
+    qdev_init_nofail(&dev->qdev);
+    return pci_bridge_get_sec_bus(br);
+}
+
+static int pci_dec_21154_device_init(SysBusDevice *dev)
+{
+    PCIHostState *phb;
+
+    phb = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-data-idx", 0x1000);
+    sysbus_init_mmio(dev, &phb->conf_mem);
+    sysbus_init_mmio(dev, &phb->data_mem);
+    return 0;
+}
+
+static int dec_21154_pci_host_init(PCIDevice *d)
+{
+    /* PCI2PCI bridge same values as PearPC - check this */
+    return 0;
+}
+
+static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = dec_21154_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_DEC;
+    k->device_id = PCI_DEVICE_ID_DEC_21154;
+    k->revision = 0x02;
+    k->class_id = PCI_CLASS_BRIDGE_PCI;
+    k->is_bridge = 1;
+}
+
+static const TypeInfo dec_21154_pci_host_info = {
+    .name          = "dec-21154",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = dec_21154_pci_host_class_init,
+};
+
+static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = pci_dec_21154_device_init;
+}
+
+static const TypeInfo pci_dec_21154_device_info = {
+    .name          = TYPE_DEC_21154,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(DECState),
+    .class_init    = pci_dec_21154_device_class_init,
+};
+
+static void dec_register_types(void)
+{
+    type_register_static(&pci_dec_21154_device_info);
+    type_register_static(&dec_21154_pci_host_info);
+    type_register_static(&dec_21154_pci_bridge_info);
+}
+
+type_init(dec_register_types)
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
new file mode 100644 (file)
index 0000000..69344d9
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * QEMU Grackle PCI host (heathrow OldWorld PowerMac)
+ *
+ * Copyright (c) 2006-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/pci/pci_host.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+
+/* debug Grackle */
+//#define DEBUG_GRACKLE
+
+#ifdef DEBUG_GRACKLE
+#define GRACKLE_DPRINTF(fmt, ...)                               \
+    do { printf("GRACKLE: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define GRACKLE_DPRINTF(fmt, ...)
+#endif
+
+#define GRACKLE_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
+
+typedef struct GrackleState {
+    PCIHostState parent_obj;
+
+    MemoryRegion pci_mmio;
+    MemoryRegion pci_hole;
+} GrackleState;
+
+/* Don't know if this matches real hardware, but it agrees with OHW.  */
+static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return (irq_num + (pci_dev->devfn >> 3)) & 3;
+}
+
+static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    GRACKLE_DPRINTF("set_irq num %d level %d\n", irq_num, level);
+    qemu_set_irq(pic[irq_num + 0x15], level);
+}
+
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    PCIHostState *phb;
+    GrackleState *d;
+
+    dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    phb = PCI_HOST_BRIDGE(dev);
+    d = GRACKLE_PCI_HOST_BRIDGE(dev);
+
+    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+                             0x80000000ULL, 0x7e000000ULL);
+    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
+                                &d->pci_hole);
+
+    phb->bus = pci_register_bus(dev, "pci",
+                                pci_grackle_set_irq,
+                                pci_grackle_map_irq,
+                                pic,
+                                &d->pci_mmio,
+                                address_space_io,
+                                0, 4, TYPE_PCI_BUS);
+
+    pci_create_simple(phb->bus, 0, "grackle");
+
+    sysbus_mmio_map(s, 0, base);
+    sysbus_mmio_map(s, 1, base + 0x00200000);
+
+    return phb->bus;
+}
+
+static int pci_grackle_init_device(SysBusDevice *dev)
+{
+    PCIHostState *phb;
+
+    phb = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-data-idx", 0x1000);
+    sysbus_init_mmio(dev, &phb->conf_mem);
+    sysbus_init_mmio(dev, &phb->data_mem);
+
+    return 0;
+}
+
+static int grackle_pci_host_init(PCIDevice *d)
+{
+    d->config[0x09] = 0x01;
+    return 0;
+}
+
+static void grackle_pci_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init      = grackle_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+    dc->no_user = 1;
+}
+
+static const TypeInfo grackle_pci_info = {
+    .name          = "grackle",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init = grackle_pci_class_init,
+};
+
+static void pci_grackle_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = pci_grackle_init_device;
+    dc->no_user = 1;
+}
+
+static const TypeInfo grackle_pci_host_info = {
+    .name          = TYPE_GRACKLE_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(GrackleState),
+    .class_init    = pci_grackle_class_init,
+};
+
+static void grackle_register_types(void)
+{
+    type_register_static(&grackle_pci_info);
+    type_register_static(&grackle_pci_host_info);
+}
+
+type_init(grackle_register_types)
diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c
new file mode 100644 (file)
index 0000000..7181bd6
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * QEMU i440FX/PIIX3 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2011 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ * Copyright (c) 2012 Jason Baron <jbaron@redhat.com>
+ *
+ * Split out from piix_pci.c
+ *
+ * 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 "sysemu/sysemu.h"
+#include "hw/pci-host/pam.h"
+
+void smram_update(MemoryRegion *smram_region, uint8_t smram,
+                  uint8_t smm_enabled)
+{
+    bool smram_enabled;
+
+    smram_enabled = ((smm_enabled && (smram & SMRAM_G_SMRAME)) ||
+                        (smram & SMRAM_D_OPEN));
+    memory_region_set_enabled(smram_region, !smram_enabled);
+}
+
+void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
+                   MemoryRegion *smram_region)
+{
+    uint8_t smm_enabled = (smm != 0);
+    if (*host_smm_enabled != smm_enabled) {
+        *host_smm_enabled = smm_enabled;
+        smram_update(smram_region, smram, *host_smm_enabled);
+    }
+}
+
+void init_pam(MemoryRegion *ram_memory, MemoryRegion *system_memory,
+              MemoryRegion *pci_address_space, PAMMemoryRegion *mem,
+              uint32_t start, uint32_t size)
+{
+    int i;
+
+    /* RAM */
+    memory_region_init_alias(&mem->alias[3], "pam-ram", ram_memory,
+                             start, size);
+    /* ROM (XXX: not quite correct) */
+    memory_region_init_alias(&mem->alias[1], "pam-rom", ram_memory,
+                             start, size);
+    memory_region_set_readonly(&mem->alias[1], true);
+
+    /* XXX: should distinguish read/write cases */
+    memory_region_init_alias(&mem->alias[0], "pam-pci", pci_address_space,
+                             start, size);
+    memory_region_init_alias(&mem->alias[2], "pam-pci", pci_address_space,
+                             start, size);
+
+    for (i = 0; i < 4; ++i) {
+        memory_region_set_enabled(&mem->alias[i], false);
+        memory_region_add_subregion_overlap(system_memory, start,
+                                            &mem->alias[i], 1);
+    }
+    mem->current = 0;
+}
+
+void pam_update(PAMMemoryRegion *pam, int idx, uint8_t val)
+{
+    assert(0 <= idx && idx <= 12);
+
+    memory_region_set_enabled(&pam->alias[pam->current], false);
+    pam->current = (val >> ((!(idx & 1)) * 4)) & PAM_ATTR_MASK;
+    memory_region_set_enabled(&pam->alias[pam->current], true);
+}
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
new file mode 100644 (file)
index 0000000..f9e68c3
--- /dev/null
@@ -0,0 +1,657 @@
+/*
+ * QEMU i440FX/PIIX3 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/isa/isa.h"
+#include "hw/sysbus.h"
+#include "qemu/range.h"
+#include "hw/xen/xen.h"
+#include "hw/pci-host/pam.h"
+#include "sysemu/sysemu.h"
+
+/*
+ * I440FX chipset data sheet.
+ * http://download.intel.com/design/chipsets/datashts/29054901.pdf
+ */
+
+typedef struct I440FXState {
+    PCIHostState parent_obj;
+} I440FXState;
+
+#define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
+#define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
+#define XEN_PIIX_NUM_PIRQS      128ULL
+#define PIIX_PIRQC              0x60
+
+/*
+ * Reset Control Register: PCI-accessible ISA-Compatible Register at address
+ * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
+ */
+#define RCR_IOPORT 0xcf9
+
+typedef struct PIIX3State {
+    PCIDevice dev;
+
+    /*
+     * bitmap to track pic levels.
+     * The pic level is the logical OR of all the PCI irqs mapped to it
+     * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
+     *
+     * PIRQ is mapped to PIC pins, we track it by
+     * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
+     * pic_irq * PIIX_NUM_PIRQS + pirq
+     */
+#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
+#error "unable to encode pic state in 64bit in pic_levels."
+#endif
+    uint64_t pic_levels;
+
+    qemu_irq *pic;
+
+    /* This member isn't used. Just for save/load compatibility */
+    int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+
+    /* Reset Control Register contents */
+    uint8_t rcr;
+
+    /* IO memory region for Reset Control Register (RCR_IOPORT) */
+    MemoryRegion rcr_mem;
+} PIIX3State;
+
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+#define I440FX_PCI_DEVICE(obj) \
+    OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+
+struct PCII440FXState {
+    PCIDevice dev;
+    MemoryRegion *system_memory;
+    MemoryRegion *pci_address_space;
+    MemoryRegion *ram_memory;
+    MemoryRegion pci_hole;
+    MemoryRegion pci_hole_64bit;
+    PAMMemoryRegion pam_regions[13];
+    MemoryRegion smram_region;
+    uint8_t smm_enabled;
+};
+
+
+#define I440FX_PAM      0x59
+#define I440FX_PAM_SIZE 7
+#define I440FX_SMRAM    0x72
+
+static void piix3_set_irq(void *opaque, int pirq, int level);
+static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx);
+static void piix3_write_config_xen(PCIDevice *dev,
+                               uint32_t address, uint32_t val, int len);
+
+/* return the global irq number corresponding to a given device irq
+   pin. We could also use the bus number to have a more precise
+   mapping. */
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
+{
+    int slot_addend;
+    slot_addend = (pci_dev->devfn >> 3) - 1;
+    return (pci_intx + slot_addend) & 3;
+}
+
+static void i440fx_update_memory_mappings(PCII440FXState *d)
+{
+    int i;
+
+    memory_region_transaction_begin();
+    for (i = 0; i < 13; i++) {
+        pam_update(&d->pam_regions[i], i,
+                   d->dev.config[I440FX_PAM + ((i + 1) / 2)]);
+    }
+    smram_update(&d->smram_region, d->dev.config[I440FX_SMRAM], d->smm_enabled);
+    memory_region_transaction_commit();
+}
+
+static void i440fx_set_smm(int val, void *arg)
+{
+    PCII440FXState *d = arg;
+
+    memory_region_transaction_begin();
+    smram_set_smm(&d->smm_enabled, val, d->dev.config[I440FX_SMRAM],
+                  &d->smram_region);
+    memory_region_transaction_commit();
+}
+
+
+static void i440fx_write_config(PCIDevice *dev,
+                                uint32_t address, uint32_t val, int len)
+{
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
+
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(dev, address, val, len);
+    if (ranges_overlap(address, len, I440FX_PAM, I440FX_PAM_SIZE) ||
+        range_covers_byte(address, len, I440FX_SMRAM)) {
+        i440fx_update_memory_mappings(d);
+    }
+}
+
+static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
+{
+    PCII440FXState *d = opaque;
+    int ret, i;
+
+    ret = pci_device_load(&d->dev, f);
+    if (ret < 0)
+        return ret;
+    i440fx_update_memory_mappings(d);
+    qemu_get_8s(f, &d->smm_enabled);
+
+    if (version_id == 2) {
+        for (i = 0; i < PIIX_NUM_PIRQS; i++) {
+            qemu_get_be32(f); /* dummy load for compatibility */
+        }
+    }
+
+    return 0;
+}
+
+static int i440fx_post_load(void *opaque, int version_id)
+{
+    PCII440FXState *d = opaque;
+
+    i440fx_update_memory_mappings(d);
+    return 0;
+}
+
+static const VMStateDescription vmstate_i440fx = {
+    .name = "I440FX",
+    .version_id = 3,
+    .minimum_version_id = 3,
+    .minimum_version_id_old = 1,
+    .load_state_old = i440fx_load_old,
+    .post_load = i440fx_post_load,
+    .fields      = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(dev, PCII440FXState),
+        VMSTATE_UINT8(smm_enabled, PCII440FXState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int i440fx_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, 0xcf8, &s->conf_mem);
+    sysbus_init_ioports(&s->busdev, 0xcf8, 4);
+
+    memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
+                          "pci-conf-data", 4);
+    sysbus_add_io(dev, 0xcfc, &s->data_mem);
+    sysbus_init_ioports(&s->busdev, 0xcfc, 4);
+
+    return 0;
+}
+
+static int i440fx_initfn(PCIDevice *dev)
+{
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
+
+    d->dev.config[I440FX_SMRAM] = 0x02;
+
+    cpu_smm_register(&i440fx_set_smm, d);
+    return 0;
+}
+
+static PCIBus *i440fx_common_init(const char *device_name,
+                                  PCII440FXState **pi440fx_state,
+                                  int *piix3_devfn,
+                                  ISABus **isa_bus, qemu_irq *pic,
+                                  MemoryRegion *address_space_mem,
+                                  MemoryRegion *address_space_io,
+                                  ram_addr_t ram_size,
+                                  hwaddr pci_hole_start,
+                                  hwaddr pci_hole_size,
+                                  hwaddr pci_hole64_start,
+                                  hwaddr pci_hole64_size,
+                                  MemoryRegion *pci_address_space,
+                                  MemoryRegion *ram_memory)
+{
+    DeviceState *dev;
+    PCIBus *b;
+    PCIDevice *d;
+    PCIHostState *s;
+    PIIX3State *piix3;
+    PCII440FXState *f;
+    unsigned i;
+
+    dev = qdev_create(NULL, "i440FX-pcihost");
+    s = PCI_HOST_BRIDGE(dev);
+    b = pci_bus_new(dev, NULL, pci_address_space,
+                    address_space_io, 0, TYPE_PCI_BUS);
+    s->bus = b;
+    object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
+    qdev_init_nofail(dev);
+
+    d = pci_create_simple(b, 0, device_name);
+    *pi440fx_state = I440FX_PCI_DEVICE(d);
+    f = *pi440fx_state;
+    f->system_memory = address_space_mem;
+    f->pci_address_space = pci_address_space;
+    f->ram_memory = ram_memory;
+    memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space,
+                             pci_hole_start, pci_hole_size);
+    memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole);
+    memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64",
+                             f->pci_address_space,
+                             pci_hole64_start, pci_hole64_size);
+    if (pci_hole64_size) {
+        memory_region_add_subregion(f->system_memory, pci_hole64_start,
+                                    &f->pci_hole_64bit);
+    }
+    memory_region_init_alias(&f->smram_region, "smram-region",
+                             f->pci_address_space, 0xa0000, 0x20000);
+    memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
+                                        &f->smram_region, 1);
+    memory_region_set_enabled(&f->smram_region, false);
+    init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+             &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
+    for (i = 0; i < 12; ++i) {
+        init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
+                 &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
+                 PAM_EXPAN_SIZE);
+    }
+
+    /* Xen supports additional interrupt routes from the PCI devices to
+     * the IOAPIC: the four pins of each PCI device on the bus are also
+     * connected to the IOAPIC directly.
+     * These additional routes can be discovered through ACPI. */
+    if (xen_enabled()) {
+        piix3 = DO_UPCAST(PIIX3State, dev,
+                pci_create_simple_multifunction(b, -1, true, "PIIX3-xen"));
+        pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+                piix3, XEN_PIIX_NUM_PIRQS);
+    } else {
+        piix3 = DO_UPCAST(PIIX3State, dev,
+                pci_create_simple_multifunction(b, -1, true, "PIIX3"));
+        pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
+                PIIX_NUM_PIRQS);
+        pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
+    }
+    piix3->pic = pic;
+    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+
+    *piix3_devfn = piix3->dev.devfn;
+
+    ram_size = ram_size / 8 / 1024 / 1024;
+    if (ram_size > 255)
+        ram_size = 255;
+    (*pi440fx_state)->dev.config[0x57]=ram_size;
+
+    i440fx_update_memory_mappings(f);
+
+    return b;
+}
+
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
+                    ISABus **isa_bus, qemu_irq *pic,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    ram_addr_t ram_size,
+                    hwaddr pci_hole_start,
+                    hwaddr pci_hole_size,
+                    hwaddr pci_hole64_start,
+                    hwaddr pci_hole64_size,
+                    MemoryRegion *pci_memory, MemoryRegion *ram_memory)
+
+{
+    PCIBus *b;
+
+    b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
+                           piix3_devfn, isa_bus, pic,
+                           address_space_mem, address_space_io, ram_size,
+                           pci_hole_start, pci_hole_size,
+                           pci_hole64_start, pci_hole64_size,
+                           pci_memory, ram_memory);
+    return b;
+}
+
+/* PIIX3 PCI to ISA bridge */
+static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
+{
+    qemu_set_irq(piix3->pic[pic_irq],
+                 !!(piix3->pic_levels &
+                    (((1ULL << PIIX_NUM_PIRQS) - 1) <<
+                     (pic_irq * PIIX_NUM_PIRQS))));
+}
+
+static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
+{
+    int pic_irq;
+    uint64_t mask;
+
+    pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
+    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
+        return;
+    }
+
+    mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
+    piix3->pic_levels &= ~mask;
+    piix3->pic_levels |= mask * !!level;
+
+    piix3_set_irq_pic(piix3, pic_irq);
+}
+
+static void piix3_set_irq(void *opaque, int pirq, int level)
+{
+    PIIX3State *piix3 = opaque;
+    piix3_set_irq_level(piix3, pirq, level);
+}
+
+static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
+{
+    PIIX3State *piix3 = opaque;
+    int irq = piix3->dev.config[PIIX_PIRQC + pin];
+    PCIINTxRoute route;
+
+    if (irq < PIIX_NUM_PIC_IRQS) {
+        route.mode = PCI_INTX_ENABLED;
+        route.irq = irq;
+    } else {
+        route.mode = PCI_INTX_DISABLED;
+        route.irq = -1;
+    }
+    return route;
+}
+
+/* irq routing is changed. so rebuild bitmap */
+static void piix3_update_irq_levels(PIIX3State *piix3)
+{
+    int pirq;
+
+    piix3->pic_levels = 0;
+    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
+        piix3_set_irq_level(piix3, pirq,
+                            pci_bus_get_irq_level(piix3->dev.bus, pirq));
+    }
+}
+
+static void piix3_write_config(PCIDevice *dev,
+                               uint32_t address, uint32_t val, int len)
+{
+    pci_default_write_config(dev, address, val, len);
+    if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
+        PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
+        int pic_irq;
+
+        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
+        piix3_update_irq_levels(piix3);
+        for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
+            piix3_set_irq_pic(piix3, pic_irq);
+        }
+    }
+}
+
+static void piix3_write_config_xen(PCIDevice *dev,
+                               uint32_t address, uint32_t val, int len)
+{
+    xen_piix_pci_write_config_client(address, val, len);
+    piix3_write_config(dev, address, val, len);
+}
+
+static void piix3_reset(void *opaque)
+{
+    PIIX3State *d = opaque;
+    uint8_t *pci_conf = d->dev.config;
+
+    pci_conf[0x04] = 0x07; /* master, memory and I/O */
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x80;
+    pci_conf[0x61] = 0x80;
+    pci_conf[0x62] = 0x80;
+    pci_conf[0x63] = 0x80;
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
+    pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+
+    d->pic_levels = 0;
+    d->rcr = 0;
+}
+
+static int piix3_post_load(void *opaque, int version_id)
+{
+    PIIX3State *piix3 = opaque;
+    piix3_update_irq_levels(piix3);
+    return 0;
+}
+
+static void piix3_pre_save(void *opaque)
+{
+    int i;
+    PIIX3State *piix3 = opaque;
+
+    for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
+        piix3->pci_irq_levels_vmstate[i] =
+            pci_bus_get_irq_level(piix3->dev.bus, i);
+    }
+}
+
+static bool piix3_rcr_needed(void *opaque)
+{
+    PIIX3State *piix3 = opaque;
+
+    return (piix3->rcr != 0);
+}
+
+static const VMStateDescription vmstate_piix3_rcr = {
+    .name = "PIIX3/rcr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(rcr, PIIX3State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_piix3 = {
+    .name = "PIIX3",
+    .version_id = 3,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .post_load = piix3_post_load,
+    .pre_save = piix3_pre_save,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, PIIX3State),
+        VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
+                              PIIX_NUM_PIRQS, 3),
+        VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmstate_piix3_rcr,
+            .needed = piix3_rcr_needed,
+        },
+        { 0 }
+    }
+};
+
+
+static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
+{
+    PIIX3State *d = opaque;
+
+    if (val & 4) {
+        qemu_system_reset_request();
+        return;
+    }
+    d->rcr = val & 2; /* keep System Reset type only */
+}
+
+static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
+{
+    PIIX3State *d = opaque;
+
+    return d->rcr;
+}
+
+static const MemoryRegionOps rcr_ops = {
+    .read = rcr_read,
+    .write = rcr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN
+};
+
+static int piix3_initfn(PCIDevice *dev)
+{
+    PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
+
+    isa_bus_new(DEVICE(d), pci_address_space_io(dev));
+
+    memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
+    memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
+                                        &d->rcr_mem, 1);
+
+    qemu_register_reset(piix3_reset, d);
+    return 0;
+}
+
+static void piix3_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    dc->desc        = "ISA bridge";
+    dc->vmsd        = &vmstate_piix3;
+    dc->no_user     = 1,
+    k->no_hotplug   = 1;
+    k->init         = piix3_initfn;
+    k->config_write = piix3_write_config;
+    k->vendor_id    = PCI_VENDOR_ID_INTEL;
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
+    k->class_id     = PCI_CLASS_BRIDGE_ISA;
+}
+
+static const TypeInfo piix3_info = {
+    .name          = "PIIX3",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PIIX3State),
+    .class_init    = piix3_class_init,
+};
+
+static void piix3_xen_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    dc->desc        = "ISA bridge";
+    dc->vmsd        = &vmstate_piix3;
+    dc->no_user     = 1;
+    k->no_hotplug   = 1;
+    k->init         = piix3_initfn;
+    k->config_write = piix3_write_config_xen;
+    k->vendor_id    = PCI_VENDOR_ID_INTEL;
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
+    k->class_id     = PCI_CLASS_BRIDGE_ISA;
+};
+
+static const TypeInfo piix3_xen_info = {
+    .name          = "PIIX3-xen",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PIIX3State),
+    .class_init    = piix3_xen_class_init,
+};
+
+static void i440fx_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->no_hotplug = 1;
+    k->init = i440fx_initfn;
+    k->config_write = i440fx_write_config;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_82441;
+    k->revision = 0x02;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    dc->desc = "Host bridge";
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_i440fx;
+}
+
+static const TypeInfo i440fx_info = {
+    .name          = TYPE_I440FX_PCI_DEVICE,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCII440FXState),
+    .class_init    = i440fx_class_init,
+};
+
+static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = i440fx_pcihost_initfn;
+    dc->fw_name = "pci";
+    dc->no_user = 1;
+}
+
+static const TypeInfo i440fx_pcihost_info = {
+    .name          = "i440FX-pcihost",
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(I440FXState),
+    .class_init    = i440fx_pcihost_class_init,
+};
+
+static void i440fx_register_types(void)
+{
+    type_register_static(&i440fx_info);
+    type_register_static(&piix3_info);
+    type_register_static(&piix3_xen_info);
+    type_register_static(&i440fx_pcihost_info);
+}
+
+type_init(i440fx_register_types)
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
new file mode 100644 (file)
index 0000000..5e7ad94
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * QEMU PowerPC E500 embedded processors pci controller emulation
+ *
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu,     <yu.liu@freescale.com>
+ *
+ * This file is derived from hw/ppc4xx_pci.c,
+ * the copyright for that material belongs to the original owners.
+ *
+ * This 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 of the  License, or
+ * (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/ppc/e500-ccsr.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "qemu/bswap.h"
+#include "hw/pci-host/ppce500.h"
+
+#ifdef DEBUG_PCI
+#define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
+#else
+#define pci_debug(fmt, ...)
+#endif
+
+#define PCIE500_CFGADDR       0x0
+#define PCIE500_CFGDATA       0x4
+#define PCIE500_REG_BASE      0xC00
+#define PCIE500_ALL_SIZE      0x1000
+#define PCIE500_REG_SIZE      (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
+
+#define PCIE500_PCI_IOLEN     0x10000ULL
+
+#define PPCE500_PCI_CONFIG_ADDR         0x0
+#define PPCE500_PCI_CONFIG_DATA         0x4
+#define PPCE500_PCI_INTACK              0x8
+
+#define PPCE500_PCI_OW1                 (0xC20 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW2                 (0xC40 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW3                 (0xC60 - PCIE500_REG_BASE)
+#define PPCE500_PCI_OW4                 (0xC80 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW3                 (0xDA0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW2                 (0xDC0 - PCIE500_REG_BASE)
+#define PPCE500_PCI_IW1                 (0xDE0 - PCIE500_REG_BASE)
+
+#define PPCE500_PCI_GASKET_TIMR         (0xE20 - PCIE500_REG_BASE)
+
+#define PCI_POTAR               0x0
+#define PCI_POTEAR              0x4
+#define PCI_POWBAR              0x8
+#define PCI_POWAR               0x10
+
+#define PCI_PITAR               0x0
+#define PCI_PIWBAR              0x8
+#define PCI_PIWBEAR             0xC
+#define PCI_PIWAR               0x10
+
+#define PPCE500_PCI_NR_POBS     5
+#define PPCE500_PCI_NR_PIBS     3
+
+struct  pci_outbound {
+    uint32_t potar;
+    uint32_t potear;
+    uint32_t powbar;
+    uint32_t powar;
+};
+
+struct pci_inbound {
+    uint32_t pitar;
+    uint32_t piwbar;
+    uint32_t piwbear;
+    uint32_t piwar;
+};
+
+#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
+
+#define PPC_E500_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
+
+struct PPCE500PCIState {
+    PCIHostState parent_obj;
+
+    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
+    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
+    uint32_t gasket_time;
+    qemu_irq irq[4];
+    uint32_t first_slot;
+    /* mmio maps */
+    MemoryRegion container;
+    MemoryRegion iomem;
+    MemoryRegion pio;
+};
+
+#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
+#define PPC_E500_PCI_BRIDGE(obj) \
+    OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE)
+
+struct PPCE500PCIBridgeState {
+    /*< private >*/
+    PCIDevice parent;
+    /*< public >*/
+
+    MemoryRegion bar0;
+};
+
+typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState;
+typedef struct PPCE500PCIState PPCE500PCIState;
+
+static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    PPCE500PCIState *pci = opaque;
+    unsigned long win;
+    uint32_t value = 0;
+    int idx;
+
+    win = addr & 0xfe0;
+
+    switch (win) {
+    case PPCE500_PCI_OW1:
+    case PPCE500_PCI_OW2:
+    case PPCE500_PCI_OW3:
+    case PPCE500_PCI_OW4:
+        idx = (addr >> 5) & 0x7;
+        switch (addr & 0xC) {
+        case PCI_POTAR:
+            value = pci->pob[idx].potar;
+            break;
+        case PCI_POTEAR:
+            value = pci->pob[idx].potear;
+            break;
+        case PCI_POWBAR:
+            value = pci->pob[idx].powbar;
+            break;
+        case PCI_POWAR:
+            value = pci->pob[idx].powar;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case PPCE500_PCI_IW3:
+    case PPCE500_PCI_IW2:
+    case PPCE500_PCI_IW1:
+        idx = ((addr >> 5) & 0x3) - 1;
+        switch (addr & 0xC) {
+        case PCI_PITAR:
+            value = pci->pib[idx].pitar;
+            break;
+        case PCI_PIWBAR:
+            value = pci->pib[idx].piwbar;
+            break;
+        case PCI_PIWBEAR:
+            value = pci->pib[idx].piwbear;
+            break;
+        case PCI_PIWAR:
+            value = pci->pib[idx].piwar;
+            break;
+        default:
+            break;
+        };
+        break;
+
+    case PPCE500_PCI_GASKET_TIMR:
+        value = pci->gasket_time;
+        break;
+
+    default:
+        break;
+    }
+
+    pci_debug("%s: win:%lx(addr:" TARGET_FMT_plx ") -> value:%x\n", __func__,
+              win, addr, value);
+    return value;
+}
+
+static void pci_reg_write4(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    PPCE500PCIState *pci = opaque;
+    unsigned long win;
+    int idx;
+
+    win = addr & 0xfe0;
+
+    pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
+              __func__, (unsigned)value, win, addr);
+
+    switch (win) {
+    case PPCE500_PCI_OW1:
+    case PPCE500_PCI_OW2:
+    case PPCE500_PCI_OW3:
+    case PPCE500_PCI_OW4:
+        idx = (addr >> 5) & 0x7;
+        switch (addr & 0xC) {
+        case PCI_POTAR:
+            pci->pob[idx].potar = value;
+            break;
+        case PCI_POTEAR:
+            pci->pob[idx].potear = value;
+            break;
+        case PCI_POWBAR:
+            pci->pob[idx].powbar = value;
+            break;
+        case PCI_POWAR:
+            pci->pob[idx].powar = value;
+            break;
+        default:
+            break;
+        };
+        break;
+
+    case PPCE500_PCI_IW3:
+    case PPCE500_PCI_IW2:
+    case PPCE500_PCI_IW1:
+        idx = ((addr >> 5) & 0x3) - 1;
+        switch (addr & 0xC) {
+        case PCI_PITAR:
+            pci->pib[idx].pitar = value;
+            break;
+        case PCI_PIWBAR:
+            pci->pib[idx].piwbar = value;
+            break;
+        case PCI_PIWBEAR:
+            pci->pib[idx].piwbear = value;
+            break;
+        case PCI_PIWAR:
+            pci->pib[idx].piwar = value;
+            break;
+        default:
+            break;
+        };
+        break;
+
+    case PPCE500_PCI_GASKET_TIMR:
+        pci->gasket_time = value;
+        break;
+
+    default:
+        break;
+    };
+}
+
+static const MemoryRegionOps e500_pci_reg_ops = {
+    .read = pci_reg_read4,
+    .write = pci_reg_write4,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int devno = pci_dev->devfn >> 3;
+    int ret;
+
+    ret = ppce500_pci_map_irq_slot(devno, irq_num);
+
+    pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
+           pci_dev->devfn, irq_num, ret, devno);
+
+    return ret;
+}
+
+static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
+
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static const VMStateDescription vmstate_pci_outbound = {
+    .name = "pci_outbound",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(potar, struct pci_outbound),
+        VMSTATE_UINT32(potear, struct pci_outbound),
+        VMSTATE_UINT32(powbar, struct pci_outbound),
+        VMSTATE_UINT32(powar, struct pci_outbound),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_pci_inbound = {
+    .name = "pci_inbound",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(pitar, struct pci_inbound),
+        VMSTATE_UINT32(piwbar, struct pci_inbound),
+        VMSTATE_UINT32(piwbear, struct pci_inbound),
+        VMSTATE_UINT32(piwar, struct pci_inbound),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_ppce500_pci = {
+    .name = "ppce500_pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
+                             vmstate_pci_outbound, struct pci_outbound),
+        VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
+                             vmstate_pci_outbound, struct pci_inbound),
+        VMSTATE_UINT32(gasket_time, PPCE500PCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+#include "exec/address-spaces.h"
+
+static int e500_pcihost_bridge_initfn(PCIDevice *d)
+{
+    PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d);
+    PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(),
+                                  "/e500-ccsr"));
+
+    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
+    d->config[PCI_HEADER_TYPE] =
+        (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
+        PCI_HEADER_TYPE_BRIDGE;
+
+    memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space,
+                             0, int128_get64(ccsr->ccsr_space.size));
+    pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
+
+    return 0;
+}
+
+static int e500_pcihost_initfn(SysBusDevice *dev)
+{
+    PCIHostState *h;
+    PPCE500PCIState *s;
+    PCIBus *b;
+    int i;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC_E500_PCI_HOST_BRIDGE(dev);
+
+    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN);
+
+    b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
+                         mpc85xx_pci_map_irq, s->irq, address_space_mem,
+                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
+    h->bus = b;
+
+    pci_create_simple(b, 0, "e500-host-bridge");
+
+    memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+                          "pci-conf-data", 4);
+    memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
+                          "pci.reg", PCIE500_REG_SIZE);
+    memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
+    memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
+    memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
+    sysbus_init_mmio(dev, &s->container);
+    sysbus_init_mmio(dev, &s->pio);
+
+    return 0;
+}
+
+static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = e500_pcihost_bridge_initfn;
+    k->vendor_id = PCI_VENDOR_ID_FREESCALE;
+    k->device_id = PCI_DEVICE_ID_MPC8533E;
+    k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
+    dc->desc = "Host bridge";
+}
+
+static const TypeInfo e500_host_bridge_info = {
+    .name          = "e500-host-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PPCE500PCIBridgeState),
+    .class_init    = e500_host_bridge_class_init,
+};
+
+static Property pcihost_properties[] = {
+    DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void e500_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = e500_pcihost_initfn;
+    dc->props = pcihost_properties;
+    dc->vmsd = &vmstate_ppce500_pci;
+}
+
+static const TypeInfo e500_pcihost_info = {
+    .name          = TYPE_PPC_E500_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PPCE500PCIState),
+    .class_init    = e500_pcihost_class_init,
+};
+
+static void e500_pci_register_types(void)
+{
+    type_register_static(&e500_pcihost_info);
+    type_register_static(&e500_host_bridge_info);
+}
+
+type_init(e500_pci_register_types)
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
new file mode 100644 (file)
index 0000000..6130253
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * QEMU PREP PCI host
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2011-2013 Andreas Färber
+ *
+ * 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/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
+#include "hw/i386/pc.h"
+#include "exec/address-spaces.h"
+
+#define TYPE_RAVEN_PCI_DEVICE "raven"
+#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
+
+#define RAVEN_PCI_DEVICE(obj) \
+    OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE)
+
+typedef struct RavenPCIState {
+    PCIDevice dev;
+} RavenPCIState;
+
+#define RAVEN_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
+
+typedef struct PRePPCIState {
+    PCIHostState parent_obj;
+
+    MemoryRegion intack;
+    qemu_irq irq[4];
+    PCIBus pci_bus;
+    RavenPCIState pci_dev;
+} PREPPCIState;
+
+static inline uint32_t PPC_PCIIO_config(hwaddr addr)
+{
+    int i;
+
+    for (i = 0; i < 11; i++) {
+        if ((addr & (1 << (11 + i))) != 0) {
+            break;
+        }
+    }
+    return (addr & 0x7ff) |  (i << 11);
+}
+
+static void ppc_pci_io_write(void *opaque, hwaddr addr,
+                             uint64_t val, unsigned int size)
+{
+    PREPPCIState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
+}
+
+static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr,
+                                unsigned int size)
+{
+    PREPPCIState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
+}
+
+static const MemoryRegionOps PPC_PCIIO_ops = {
+    .read = ppc_pci_io_read,
+    .write = ppc_pci_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static uint64_t ppc_intack_read(void *opaque, hwaddr addr,
+                                unsigned int size)
+{
+    return pic_read_irq(isa_pic);
+}
+
+static const MemoryRegionOps PPC_intack_ops = {
+    .read = ppc_intack_read,
+    .valid = {
+        .max_access_size = 1,
+    },
+};
+
+static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return (irq_num + (pci_dev->devfn >> 3)) & 1;
+}
+
+static void prep_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    qemu_set_irq(pic[irq_num] , level);
+}
+
+static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
+{
+    SysBusDevice *dev = SYS_BUS_DEVICE(d);
+    PCIHostState *h = PCI_HOST_BRIDGE(dev);
+    PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
+    MemoryRegion *address_space_mem = get_system_memory();
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s,
+                          "pci-conf-idx", 1);
+    sysbus_add_io(dev, 0xcf8, &h->conf_mem);
+    sysbus_init_ioports(&h->busdev, 0xcf8, 1);
+
+    memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s,
+                          "pci-conf-data", 1);
+    sysbus_add_io(dev, 0xcfc, &h->data_mem);
+    sysbus_init_ioports(&h->busdev, 0xcfc, 1);
+
+    memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
+    memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
+
+    memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1);
+    memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
+
+    /* TODO Remove once realize propagates to child devices. */
+    object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
+}
+
+static void raven_pcihost_initfn(Object *obj)
+{
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *address_space_io = get_system_io();
+    DeviceState *pci_dev;
+
+    pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
+                        address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
+    h->bus = &s->pci_bus;
+
+    object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE);
+    pci_dev = DEVICE(&s->pci_dev);
+    qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
+    object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
+                            NULL);
+    qdev_prop_set_bit(pci_dev, "multifunction", false);
+}
+
+static int raven_init(PCIDevice *d)
+{
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x34] = 0x00; // capabilities_pointer
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_raven = {
+    .name = "raven",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, RavenPCIState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void raven_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = raven_init;
+    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
+    k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
+    k->revision = 0x00;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    dc->desc = "PReP Host Bridge - Motorola Raven";
+    dc->vmsd = &vmstate_raven;
+    dc->no_user = 1;
+}
+
+static const TypeInfo raven_info = {
+    .name = TYPE_RAVEN_PCI_DEVICE,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(RavenPCIState),
+    .class_init = raven_class_init,
+};
+
+static void raven_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = raven_pcihost_realizefn;
+    dc->fw_name = "pci";
+    dc->no_user = 1;
+}
+
+static const TypeInfo raven_pcihost_info = {
+    .name = TYPE_RAVEN_PCI_HOST_BRIDGE,
+    .parent = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PREPPCIState),
+    .instance_init = raven_pcihost_initfn,
+    .class_init = raven_pcihost_class_init,
+};
+
+static void raven_register_types(void)
+{
+    type_register_static(&raven_pcihost_info);
+    type_register_static(&raven_info);
+}
+
+type_init(raven_register_types)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
new file mode 100644 (file)
index 0000000..8467f86
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * QEMU MCH/ICH9 PCI Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2009, 2010, 2011
+ *               Isaku Yamahata <yamahata at valinux co jp>
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
+ *
+ * This is based on piix_pci.c, but heavily modified.
+ *
+ * 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/hw.h"
+#include "hw/pci-host/q35.h"
+
+/****************************************************************************
+ * Q35 host
+ */
+
+static int q35_host_init(SysBusDevice *dev)
+{
+    PCIBus *b;
+    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
+    Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev);
+
+    memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci,
+                          "pci-conf-idx", 4);
+    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
+    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
+
+    memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci,
+                          "pci-conf-data", 4);
+    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
+    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
+
+    if (pcie_host_init(&s->host) < 0) {
+        return -1;
+    }
+    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
+                    s->mch.pci_address_space, s->mch.address_space_io,
+                    0, TYPE_PCIE_BUS);
+    s->host.pci.bus = b;
+    qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
+    qdev_init_nofail(DEVICE(&s->mch));
+
+    return 0;
+}
+
+static Property mch_props[] = {
+    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
+                        MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void q35_host_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = q35_host_init;
+    dc->props = mch_props;
+}
+
+static void q35_host_initfn(Object *obj)
+{
+    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+
+    object_initialize(&s->mch, TYPE_MCH_PCI_DEVICE);
+    object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
+    qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
+    qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
+}
+
+static const TypeInfo q35_host_info = {
+    .name       = TYPE_Q35_HOST_DEVICE,
+    .parent     = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(Q35PCIHost),
+    .instance_init = q35_host_initfn,
+    .class_init = q35_host_class_init,
+};
+
+/****************************************************************************
+ * MCH D0:F0
+ */
+
+/* PCIe MMCFG */
+static void mch_update_pciexbar(MCHPCIState *mch)
+{
+    PCIDevice *pci_dev = &mch->d;
+    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
+    DeviceState *qdev = bus->parent;
+    Q35PCIHost *s = Q35_HOST_DEVICE(qdev);
+
+    uint64_t pciexbar;
+    int enable;
+    uint64_t addr;
+    uint64_t addr_mask;
+    uint32_t length;
+
+    pciexbar = pci_get_quad(pci_dev->config + MCH_HOST_BRIDGE_PCIEXBAR);
+    enable = pciexbar & MCH_HOST_BRIDGE_PCIEXBAREN;
+    addr_mask = MCH_HOST_BRIDGE_PCIEXBAR_ADMSK;
+    switch (pciexbar & MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK) {
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M:
+        length = 256 * 1024 * 1024;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M:
+        length = 128 * 1024 * 1024;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK |
+            MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M:
+        length = 64 * 1024 * 1024;
+        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
+        break;
+    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
+    default:
+        enable = 0;
+        length = 0;
+        abort();
+        break;
+    }
+    addr = pciexbar & addr_mask;
+    pcie_host_mmcfg_update(&s->host, enable, addr, length);
+}
+
+/* PAM */
+static void mch_update_pam(MCHPCIState *mch)
+{
+    int i;
+
+    memory_region_transaction_begin();
+    for (i = 0; i < 13; i++) {
+        pam_update(&mch->pam_regions[i], i,
+                   mch->d.config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]);
+    }
+    memory_region_transaction_commit();
+}
+
+/* SMRAM */
+static void mch_update_smram(MCHPCIState *mch)
+{
+    memory_region_transaction_begin();
+    smram_update(&mch->smram_region, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+                    mch->smm_enabled);
+    memory_region_transaction_commit();
+}
+
+static void mch_set_smm(int smm, void *arg)
+{
+    MCHPCIState *mch = arg;
+
+    memory_region_transaction_begin();
+    smram_set_smm(&mch->smm_enabled, smm, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
+                    &mch->smram_region);
+    memory_region_transaction_commit();
+}
+
+static void mch_write_config(PCIDevice *d,
+                              uint32_t address, uint32_t val, int len)
+{
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    /* XXX: implement SMRAM.D_LOCK */
+    pci_default_write_config(d, address, val, len);
+
+    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0,
+                       MCH_HOST_BRIDGE_PAM_SIZE)) {
+        mch_update_pam(mch);
+    }
+
+    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR,
+                       MCH_HOST_BRIDGE_PCIEXBAR_SIZE)) {
+        mch_update_pciexbar(mch);
+    }
+
+    if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM,
+                       MCH_HOST_BRDIGE_SMRAM_SIZE)) {
+        mch_update_smram(mch);
+    }
+}
+
+static void mch_update(MCHPCIState *mch)
+{
+    mch_update_pciexbar(mch);
+    mch_update_pam(mch);
+    mch_update_smram(mch);
+}
+
+static int mch_post_load(void *opaque, int version_id)
+{
+    MCHPCIState *mch = opaque;
+    mch_update(mch);
+    return 0;
+}
+
+static const VMStateDescription vmstate_mch = {
+    .name = "mch",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = mch_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(d, MCHPCIState),
+        VMSTATE_UINT8(smm_enabled, MCHPCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mch_reset(DeviceState *qdev)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
+                 MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
+
+    d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
+
+    mch_update(mch);
+}
+
+static int mch_init(PCIDevice *d)
+{
+    int i;
+    hwaddr pci_hole64_size;
+    MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+    /* setup pci memory regions */
+    memory_region_init_alias(&mch->pci_hole, "pci-hole",
+                             mch->pci_address_space,
+                             mch->below_4g_mem_size,
+                             0x100000000ULL - mch->below_4g_mem_size);
+    memory_region_add_subregion(mch->system_memory, mch->below_4g_mem_size,
+                                &mch->pci_hole);
+    pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
+                       ((uint64_t)1 << 62));
+    memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64",
+                             mch->pci_address_space,
+                             0x100000000ULL + mch->above_4g_mem_size,
+                             pci_hole64_size);
+    if (pci_hole64_size) {
+        memory_region_add_subregion(mch->system_memory,
+                                    0x100000000ULL + mch->above_4g_mem_size,
+                                    &mch->pci_hole_64bit);
+    }
+    /* smram */
+    cpu_smm_register(&mch_set_smm, mch);
+    memory_region_init_alias(&mch->smram_region, "smram-region",
+                             mch->pci_address_space, 0xa0000, 0x20000);
+    memory_region_add_subregion_overlap(mch->system_memory, 0xa0000,
+                                        &mch->smram_region, 1);
+    memory_region_set_enabled(&mch->smram_region, false);
+    init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+             &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
+    for (i = 0; i < 12; ++i) {
+        init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
+                 &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
+                 PAM_EXPAN_SIZE);
+    }
+    return 0;
+}
+
+static void mch_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = mch_init;
+    k->config_write = mch_write_config;
+    dc->reset = mch_reset;
+    dc->desc = "Host bridge";
+    dc->vmsd = &vmstate_mch;
+    k->vendor_id = PCI_VENDOR_ID_INTEL;
+    k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH;
+    k->revision = MCH_HOST_BRIDGE_REVISION_DEFUALT;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo mch_info = {
+    .name = TYPE_MCH_PCI_DEVICE,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(MCHPCIState),
+    .class_init = mch_class_init,
+};
+
+static void q35_register(void)
+{
+    type_register_static(&mch_info);
+    type_register_static(&q35_host_info);
+}
+
+type_init(q35_register);
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
new file mode 100644 (file)
index 0000000..fff235d
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * QEMU Uninorth PCI host (for all Mac99 and newer machines)
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * 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/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+
+/* debug UniNorth */
+//#define DEBUG_UNIN
+
+#ifdef DEBUG_UNIN
+#define UNIN_DPRINTF(fmt, ...)                                  \
+    do { printf("UNIN: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define UNIN_DPRINTF(fmt, ...)
+#endif
+
+static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
+
+#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
+#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
+#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
+#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
+
+#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
+#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
+#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
+#define U3_AGP_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
+
+typedef struct UNINState {
+    PCIHostState parent_obj;
+
+    MemoryRegion pci_mmio;
+    MemoryRegion pci_hole;
+} UNINState;
+
+static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int retval;
+    int devfn = pci_dev->devfn & 0x00FFFFFF;
+
+    retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
+
+    return retval;
+}
+
+static void pci_unin_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
+                 unin_irq_line[irq_num], level);
+    qemu_set_irq(pic[unin_irq_line[irq_num]], level);
+}
+
+static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
+{
+    uint32_t retval;
+
+    if (reg & (1u << 31)) {
+        /* XXX OpenBIOS compatibility hack */
+        retval = reg | (addr & 3);
+    } else if (reg & 1) {
+        /* CFA1 style */
+        retval = (reg & ~7u) | (addr & 7);
+    } else {
+        uint32_t slot, func;
+
+        /* Grab CFA0 style values */
+        slot = ffs(reg & 0xfffff800) - 1;
+        func = (reg >> 8) & 7;
+
+        /* ... and then convert them to x86 format */
+        /* config pointer */
+        retval = (reg & (0xff - 7)) | (addr & 7);
+        /* slot */
+        retval |= slot << 11;
+        /* fn */
+        retval |= func << 8;
+    }
+
+
+    UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
+                 reg, addr, retval);
+
+    return retval;
+}
+
+static void unin_data_write(void *opaque, hwaddr addr,
+                            uint64_t val, unsigned len)
+{
+    UNINState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
+                 addr, len, val);
+    pci_data_write(phb->bus,
+                   unin_get_config_reg(phb->config_reg, addr),
+                   val, len);
+}
+
+static uint64_t unin_data_read(void *opaque, hwaddr addr,
+                               unsigned len)
+{
+    UNINState *s = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    uint32_t val;
+
+    val = pci_data_read(phb->bus,
+                        unin_get_config_reg(phb->config_reg, addr),
+                        len);
+    UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
+                 addr, len, val);
+    return val;
+}
+
+static const MemoryRegionOps unin_data_ops = {
+    .read = unin_data_read,
+    .write = unin_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int pci_unin_main_init_device(SysBusDevice *dev)
+{
+    PCIHostState *h;
+
+    /* Use values found on a real PowerMac */
+    /* Uninorth main bus */
+    h = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
+                          "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
+
+    return 0;
+}
+
+
+static int pci_u3_agp_init_device(SysBusDevice *dev)
+{
+    PCIHostState *h;
+
+    /* Uninorth U3 AGP bus */
+    h = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
+                          "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
+
+    return 0;
+}
+
+static int pci_unin_agp_init_device(SysBusDevice *dev)
+{
+    PCIHostState *h;
+
+    /* Uninorth AGP bus */
+    h = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
+    return 0;
+}
+
+static int pci_unin_internal_init_device(SysBusDevice *dev)
+{
+    PCIHostState *h;
+
+    /* Uninorth internal bus */
+    h = PCI_HOST_BRIDGE(dev);
+
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
+                          dev, "pci-conf-idx", 0x1000);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
+                          dev, "pci-conf-data", 0x1000);
+    sysbus_init_mmio(dev, &h->conf_mem);
+    sysbus_init_mmio(dev, &h->data_mem);
+    return 0;
+}
+
+PCIBus *pci_pmac_init(qemu_irq *pic,
+                      MemoryRegion *address_space_mem,
+                      MemoryRegion *address_space_io)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    PCIHostState *h;
+    UNINState *d;
+
+    /* Use values found on a real PowerMac */
+    /* Uninorth main bus */
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    h = PCI_HOST_BRIDGE(s);
+    d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
+    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+                             0x80000000ULL, 0x70000000ULL);
+    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
+                                &d->pci_hole);
+
+    h->bus = pci_register_bus(dev, "pci",
+                              pci_unin_set_irq, pci_unin_map_irq,
+                              pic,
+                              &d->pci_mmio,
+                              address_space_io,
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
+
+#if 0
+    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
+#endif
+
+    sysbus_mmio_map(s, 0, 0xf2800000);
+    sysbus_mmio_map(s, 1, 0xf2c00000);
+
+    /* DEC 21154 bridge */
+#if 0
+    /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
+    pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
+#endif
+
+    /* Uninorth AGP bus */
+    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, 0xf0800000);
+    sysbus_mmio_map(s, 1, 0xf0c00000);
+
+    /* Uninorth internal bus */
+#if 0
+    /* XXX: not needed for now */
+    pci_create_simple(h->bus, PCI_DEVFN(14, 0),
+                      "uni-north-internal-pci");
+    dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, 0xf4800000);
+    sysbus_mmio_map(s, 1, 0xf4c00000);
+#endif
+
+    return h->bus;
+}
+
+PCIBus *pci_pmac_u3_init(qemu_irq *pic,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    PCIHostState *h;
+    UNINState *d;
+
+    /* Uninorth AGP bus */
+
+    dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    h = PCI_HOST_BRIDGE(dev);
+    d = U3_AGP_HOST_BRIDGE(dev);
+
+    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
+    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
+                             0x80000000ULL, 0x70000000ULL);
+    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
+                                &d->pci_hole);
+
+    h->bus = pci_register_bus(dev, "pci",
+                              pci_unin_set_irq, pci_unin_map_irq,
+                              pic,
+                              &d->pci_mmio,
+                              address_space_io,
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
+
+    sysbus_mmio_map(s, 0, 0xf0800000);
+    sysbus_mmio_map(s, 1, 0xf0c00000);
+
+    pci_create_simple(h->bus, 11 << 3, "u3-agp");
+
+    return h->bus;
+}
+
+static int unin_main_pci_host_init(PCIDevice *d)
+{
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x34] = 0x00; // capabilities_pointer
+    return 0;
+}
+
+static int unin_agp_pci_host_init(PCIDevice *d)
+{
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    //    d->config[0x34] = 0x80; // capabilities_pointer
+    return 0;
+}
+
+static int u3_agp_pci_host_init(PCIDevice *d)
+{
+    /* cache line size */
+    d->config[0x0C] = 0x08;
+    /* latency timer */
+    d->config[0x0D] = 0x10;
+    return 0;
+}
+
+static int unin_internal_pci_host_init(PCIDevice *d)
+{
+    d->config[0x0C] = 0x08; // cache_line_size
+    d->config[0x0D] = 0x10; // latency_timer
+    d->config[0x34] = 0x00; // capabilities_pointer
+    return 0;
+}
+
+static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_main_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo unin_main_pci_host_info = {
+    .name = "uni-north-pci",
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init = unin_main_pci_host_class_init,
+};
+
+static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = u3_agp_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo u3_agp_pci_host_info = {
+    .name = "u3-agp",
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init = u3_agp_pci_host_class_init,
+};
+
+static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_agp_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo unin_agp_pci_host_info = {
+    .name = "uni-north-agp",
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init = unin_agp_pci_host_class_init,
+};
+
+static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init      = unin_internal_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_APPLE;
+    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
+    k->revision  = 0x00;
+    k->class_id  = PCI_CLASS_BRIDGE_HOST;
+}
+
+static const TypeInfo unin_internal_pci_host_info = {
+    .name = "uni-north-internal-pci",
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init = unin_internal_pci_host_class_init,
+};
+
+static void pci_unin_main_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sbc->init = pci_unin_main_init_device;
+}
+
+static const TypeInfo pci_unin_main_info = {
+    .name          = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(UNINState),
+    .class_init    = pci_unin_main_class_init,
+};
+
+static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sbc->init = pci_u3_agp_init_device;
+}
+
+static const TypeInfo pci_u3_agp_info = {
+    .name          = TYPE_U3_AGP_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(UNINState),
+    .class_init    = pci_u3_agp_class_init,
+};
+
+static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sbc->init = pci_unin_agp_init_device;
+}
+
+static const TypeInfo pci_unin_agp_info = {
+    .name          = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(UNINState),
+    .class_init    = pci_unin_agp_class_init,
+};
+
+static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sbc->init = pci_unin_internal_init_device;
+}
+
+static const TypeInfo pci_unin_internal_info = {
+    .name          = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(UNINState),
+    .class_init    = pci_unin_internal_class_init,
+};
+
+static void unin_register_types(void)
+{
+    type_register_static(&unin_main_pci_host_info);
+    type_register_static(&u3_agp_pci_host_info);
+    type_register_static(&unin_agp_pci_host_info);
+    type_register_static(&unin_internal_pci_host_info);
+
+    type_register_static(&pci_unin_main_info);
+    type_register_static(&pci_u3_agp_info);
+    type_register_static(&pci_unin_agp_info);
+    type_register_static(&pci_unin_internal_info);
+}
+
+type_init(unin_register_types)
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
new file mode 100644 (file)
index 0000000..d67ca79
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * ARM Versatile/PB PCI host controller
+ *
+ * Copyright (c) 2006-2009 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq irq[4];
+    int realview;
+    MemoryRegion mem_config;
+    MemoryRegion mem_config2;
+    MemoryRegion isa;
+} PCIVPBState;
+
+static inline uint32_t vpb_pci_config_addr(hwaddr addr)
+{
+    return addr & 0xffffff;
+}
+
+static void pci_vpb_config_write(void *opaque, hwaddr addr,
+                                 uint64_t val, unsigned size)
+{
+    pci_data_write(opaque, vpb_pci_config_addr(addr), val, size);
+}
+
+static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    uint32_t val;
+    val = pci_data_read(opaque, vpb_pci_config_addr(addr), size);
+    return val;
+}
+
+static const MemoryRegionOps pci_vpb_config_ops = {
+    .read = pci_vpb_config_read,
+    .write = pci_vpb_config_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
+{
+    return irq_num;
+}
+
+static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static int pci_vpb_init(SysBusDevice *dev)
+{
+    PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
+    PCIBus *bus;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+    bus = pci_register_bus(&dev->qdev, "pci",
+                           pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           get_system_memory(), get_system_io(),
+                           PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
+
+    /* ??? Register memory space.  */
+
+    /* Our memory regions are:
+     * 0 : PCI self config window
+     * 1 : PCI config window
+     * 2 : PCI IO window (realview_pci only)
+     */
+    memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus,
+                          "pci-vpb-selfconfig", 0x1000000);
+    sysbus_init_mmio(dev, &s->mem_config);
+    memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus,
+                          "pci-vpb-config", 0x1000000);
+    sysbus_init_mmio(dev, &s->mem_config2);
+    if (s->realview) {
+        isa_mmio_setup(&s->isa, 0x0100000);
+        sysbus_init_mmio(dev, &s->isa);
+    }
+
+    pci_create_simple(bus, -1, "versatile_pci_host");
+    return 0;
+}
+
+static int pci_realview_init(SysBusDevice *dev)
+{
+    PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
+    s->realview = 1;
+    return pci_vpb_init(dev);
+}
+
+static int versatile_pci_host_init(PCIDevice *d)
+{
+    pci_set_word(d->config + PCI_STATUS,
+                PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
+    pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
+    return 0;
+}
+
+static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = versatile_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_XILINX;
+    k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
+    k->class_id = PCI_CLASS_PROCESSOR_CO;
+}
+
+static const TypeInfo versatile_pci_host_info = {
+    .name          = "versatile_pci_host",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = versatile_pci_host_class_init,
+};
+
+static void pci_vpb_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = pci_vpb_init;
+}
+
+static const TypeInfo pci_vpb_info = {
+    .name          = "versatile_pci",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PCIVPBState),
+    .class_init    = pci_vpb_class_init,
+};
+
+static void pci_realview_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = pci_realview_init;
+}
+
+static const TypeInfo pci_realview_info = {
+    .name          = "realview_pci",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PCIVPBState),
+    .class_init    = pci_realview_class_init,
+};
+
+static void versatile_pci_register_types(void)
+{
+    type_register_static(&pci_vpb_info);
+    type_register_static(&pci_realview_info);
+    type_register_static(&versatile_pci_host_info);
+}
+
+type_init(versatile_pci_register_types)
index a1511abf003e0652059770557950faea73249550..a7fb9d0c1199367d046d8a95af0aaa2aa8d95225 100644 (file)
@@ -8,6 +8,4 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
 common-obj-$(CONFIG_NO_PCI) += pci-stub.o
 common-obj-$(CONFIG_ALL) += pci-stub.o
 
-common-obj-$(CONFIG_PCI) += bridge/ host/
-
 obj-$(CONFIG_PCI_HOTPLUG) += pci-hotplug.o
diff --git a/hw/pci/bridge/Makefile.objs b/hw/pci/bridge/Makefile.objs
deleted file mode 100644 (file)
index 5dd92d2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-common-obj-y += pci_bridge_dev.o
-common-obj-y += ioh3420.o xio3130_upstream.o xio3130_downstream.o
-common-obj-y += i82801b11.o
diff --git a/hw/pci/bridge/i82801b11.c b/hw/pci/bridge/i82801b11.c
deleted file mode 100644 (file)
index 5807a92..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2006 Fabrice Bellard
- *
- * 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.
- */
-/*
- * QEMU i82801b11 dmi-to-pci Bridge Emulation
- *
- *  Copyright (c) 2009, 2010, 2011
- *                Isaku Yamahata <yamahata at valinux co jp>
- *                VA Linux Systems Japan K.K.
- *  Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
- *
- * 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 <http://www.gnu.org/licenses/>
- */
-
-#include "hw/pci/pci.h"
-#include "hw/i386/ich9.h"
-
-
-/*****************************************************************************/
-/* ICH9 DMI-to-PCI bridge */
-#define I82801ba_SSVID_OFFSET   0x50
-#define I82801ba_SSVID_SVID     0
-#define I82801ba_SSVID_SSID     0
-
-typedef struct I82801b11Bridge {
-    PCIBridge br;
-} I82801b11Bridge;
-
-static int i82801b11_bridge_initfn(PCIDevice *d)
-{
-    int rc;
-
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
-    if (rc < 0) {
-        return rc;
-    }
-
-    rc = pci_bridge_ssvid_init(d, I82801ba_SSVID_OFFSET,
-                               I82801ba_SSVID_SVID, I82801ba_SSVID_SSID);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    pci_config_set_prog_interface(d->config, PCI_CLASS_BRDIGE_PCI_INF_SUB);
-    return 0;
-
-err_bridge:
-    pci_bridge_exitfn(d);
-
-    return rc;
-}
-
-static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->is_bridge = 1;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
-    k->revision = ICH9_D2P_A2_REVISION;
-    k->init = i82801b11_bridge_initfn;
-}
-
-static const TypeInfo i82801b11_bridge_info = {
-    .name          = "i82801b11-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(I82801b11Bridge),
-    .class_init    = i82801b11_bridge_class_init,
-};
-
-PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus)
-{
-    PCIDevice *d;
-    PCIBridge *br;
-    char buf[16];
-    DeviceState *qdev;
-
-    d = pci_create_multifunction(bus, devfn, true, "i82801b11-bridge");
-    if (!d) {
-        return NULL;
-    }
-    br = DO_UPCAST(PCIBridge, dev, d);
-    qdev = &br->dev.qdev;
-
-    snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
-    pci_bridge_map_irq(br, buf, pci_swizzle_map_irq_fn);
-    qdev_init_nofail(qdev);
-
-    return pci_bridge_get_sec_bus(br);
-}
-
-static void d2pbr_register(void)
-{
-    type_register_static(&i82801b11_bridge_info);
-}
-
-type_init(d2pbr_register);
diff --git a/hw/pci/bridge/ioh3420.c b/hw/pci/bridge/ioh3420.c
deleted file mode 100644 (file)
index 5cff61e..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * ioh3420.c
- * Intel X58 north bridge IOH
- * PCI Express root port device id 3420
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * 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 of the License, or
- * (at your option) any later version.
- *
- * 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/>.
- */
-
-#include "hw/pci/pci_ids.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/pcie.h"
-#include "hw/ioh3420.h"
-
-#define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
-#define PCI_DEVICE_ID_IOH_REV           0x2
-#define IOH_EP_SSVID_OFFSET             0x40
-#define IOH_EP_SSVID_SVID               PCI_VENDOR_ID_INTEL
-#define IOH_EP_SSVID_SSID               0
-#define IOH_EP_MSI_OFFSET               0x60
-#define IOH_EP_MSI_SUPPORTED_FLAGS      PCI_MSI_FLAGS_MASKBIT
-#define IOH_EP_MSI_NR_VECTOR            2
-#define IOH_EP_EXP_OFFSET               0x90
-#define IOH_EP_AER_OFFSET               0x100
-
-/*
- * If two MSI vector are allocated, Advanced Error Interrupt Message Number
- * is 1. otherwise 0.
- * 17.12.5.10 RPERRSTS,  32:27 bit Advanced Error Interrupt Message Number.
- */
-static uint8_t ioh3420_aer_vector(const PCIDevice *d)
-{
-    switch (msi_nr_vectors_allocated(d)) {
-    case 1:
-        return 0;
-    case 2:
-        return 1;
-    case 4:
-    case 8:
-    case 16:
-    case 32:
-    default:
-        break;
-    }
-    abort();
-    return 0;
-}
-
-static void ioh3420_aer_vector_update(PCIDevice *d)
-{
-    pcie_aer_root_set_vector(d, ioh3420_aer_vector(d));
-}
-
-static void ioh3420_write_config(PCIDevice *d,
-                                   uint32_t address, uint32_t val, int len)
-{
-    uint32_t root_cmd =
-        pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
-
-    pci_bridge_write_config(d, address, val, len);
-    ioh3420_aer_vector_update(d);
-    pcie_cap_slot_write_config(d, address, val, len);
-    pcie_aer_write_config(d, address, val, len);
-    pcie_aer_root_write_config(d, address, val, len, root_cmd);
-}
-
-static void ioh3420_reset(DeviceState *qdev)
-{
-    PCIDevice *d = PCI_DEVICE(qdev);
-
-    ioh3420_aer_vector_update(d);
-    pcie_cap_root_reset(d);
-    pcie_cap_deverr_reset(d);
-    pcie_cap_slot_reset(d);
-    pcie_aer_root_reset(d);
-    pci_bridge_reset(qdev);
-    pci_bridge_disable_base_limit(d);
-}
-
-static int ioh3420_initfn(PCIDevice *d)
-{
-    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
-    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
-    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
-    int rc;
-
-    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
-    if (rc < 0) {
-        return rc;
-    }
-
-    pcie_port_init_reg(d);
-
-    rc = pci_bridge_ssvid_init(d, IOH_EP_SSVID_OFFSET,
-                               IOH_EP_SSVID_SVID, IOH_EP_SSVID_SSID);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR,
-                  IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
-                  IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = pcie_cap_init(d, IOH_EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port);
-    if (rc < 0) {
-        goto err_msi;
-    }
-    pcie_cap_deverr_init(d);
-    pcie_cap_slot_init(d, s->slot);
-    pcie_chassis_create(s->chassis);
-    rc = pcie_chassis_add_slot(s);
-    if (rc < 0) {
-        goto err_pcie_cap;
-    }
-    pcie_cap_root_init(d);
-    rc = pcie_aer_init(d, IOH_EP_AER_OFFSET);
-    if (rc < 0) {
-        goto err;
-    }
-    pcie_aer_root_init(d);
-    ioh3420_aer_vector_update(d);
-    return 0;
-
-err:
-    pcie_chassis_del_slot(s);
-err_pcie_cap:
-    pcie_cap_exit(d);
-err_msi:
-    msi_uninit(d);
-err_bridge:
-    pci_bridge_exitfn(d);
-    return rc;
-}
-
-static void ioh3420_exitfn(PCIDevice *d)
-{
-    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
-    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
-    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
-
-    pcie_aer_exit(d);
-    pcie_chassis_del_slot(s);
-    pcie_cap_exit(d);
-    msi_uninit(d);
-    pci_bridge_exitfn(d);
-}
-
-PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
-                         const char *bus_name, pci_map_irq_fn map_irq,
-                         uint8_t port, uint8_t chassis, uint16_t slot)
-{
-    PCIDevice *d;
-    PCIBridge *br;
-    DeviceState *qdev;
-
-    d = pci_create_multifunction(bus, devfn, multifunction, "ioh3420");
-    if (!d) {
-        return NULL;
-    }
-    br = DO_UPCAST(PCIBridge, dev, d);
-
-    qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
-    qdev_prop_set_uint8(qdev, "port", port);
-    qdev_prop_set_uint8(qdev, "chassis", chassis);
-    qdev_prop_set_uint16(qdev, "slot", slot);
-    qdev_init_nofail(qdev);
-
-    return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
-}
-
-static const VMStateDescription vmstate_ioh3420 = {
-    .name = "ioh-3240-express-root-port",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = pcie_cap_slot_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
-        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
-                       vmstate_pcie_aer_log, PCIEAERLog),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property ioh3420_properties[] = {
-    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
-    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
-    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
-    port.br.dev.exp.aer_log.log_max,
-    PCIE_AER_LOG_MAX_DEFAULT),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ioh3420_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->is_express = 1;
-    k->is_bridge = 1;
-    k->config_write = ioh3420_write_config;
-    k->init = ioh3420_initfn;
-    k->exit = ioh3420_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_IOH_EPORT;
-    k->revision = PCI_DEVICE_ID_IOH_REV;
-    dc->desc = "Intel IOH device id 3420 PCIE Root Port";
-    dc->reset = ioh3420_reset;
-    dc->vmsd = &vmstate_ioh3420;
-    dc->props = ioh3420_properties;
-}
-
-static const TypeInfo ioh3420_info = {
-    .name          = "ioh3420",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIESlot),
-    .class_init    = ioh3420_class_init,
-};
-
-static void ioh3420_register_types(void)
-{
-    type_register_static(&ioh3420_info);
-}
-
-type_init(ioh3420_register_types)
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
diff --git a/hw/pci/bridge/pci_bridge_dev.c b/hw/pci/bridge/pci_bridge_dev.c
deleted file mode 100644 (file)
index 971b432..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Standard PCI Bridge Device
- *
- * Copyright (c) 2011 Red Hat Inc. Author: Michael S. Tsirkin <mst@redhat.com>
- *
- * http://www.pcisig.com/specifications/conventional/pci_to_pci_bridge_architecture/
- *
- * 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 of the License, or
- * (at your option) any later version.
- *
- * 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/>.
- */
-
-#include "hw/pci/pci_bridge.h"
-#include "hw/pci/pci_ids.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/shpc.h"
-#include "hw/pci/slotid_cap.h"
-#include "exec/memory.h"
-#include "hw/pci/pci_bus.h"
-
-struct PCIBridgeDev {
-    PCIBridge bridge;
-    MemoryRegion bar;
-    uint8_t chassis_nr;
-#define PCI_BRIDGE_DEV_F_MSI_REQ 0
-    uint32_t flags;
-};
-typedef struct PCIBridgeDev PCIBridgeDev;
-
-static int pci_bridge_dev_initfn(PCIDevice *dev)
-{
-    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
-    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
-    int err;
-
-    err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
-    if (err) {
-        goto bridge_error;
-    }
-    memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev));
-    err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
-    if (err) {
-        goto shpc_error;
-    }
-    err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
-    if (err) {
-        goto slotid_error;
-    }
-    if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
-        msi_supported) {
-        err = msi_init(dev, 0, 1, true, true);
-        if (err < 0) {
-            goto msi_error;
-        }
-    }
-    /* TODO: spec recommends using 64 bit prefetcheable BAR.
-     * Check whether that works well. */
-    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
-                    PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
-    dev->config[PCI_INTERRUPT_PIN] = 0x1;
-    return 0;
-msi_error:
-    slotid_cap_cleanup(dev);
-slotid_error:
-    shpc_cleanup(dev, &bridge_dev->bar);
-shpc_error:
-    memory_region_destroy(&bridge_dev->bar);
-    pci_bridge_exitfn(dev);
-bridge_error:
-    return err;
-}
-
-static void pci_bridge_dev_exitfn(PCIDevice *dev)
-{
-    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
-    PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
-    if (msi_present(dev)) {
-        msi_uninit(dev);
-    }
-    slotid_cap_cleanup(dev);
-    shpc_cleanup(dev, &bridge_dev->bar);
-    memory_region_destroy(&bridge_dev->bar);
-    pci_bridge_exitfn(dev);
-}
-
-static void pci_bridge_dev_write_config(PCIDevice *d,
-                                        uint32_t address, uint32_t val, int len)
-{
-    pci_bridge_write_config(d, address, val, len);
-    if (msi_present(d)) {
-        msi_write_config(d, address, val, len);
-    }
-    shpc_cap_write_config(d, address, val, len);
-}
-
-static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
-{
-    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
-
-    pci_bridge_reset(qdev);
-    shpc_reset(dev);
-}
-
-static Property pci_bridge_dev_properties[] = {
-                    /* Note: 0 is not a legal chassis number. */
-    DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0),
-    DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static const VMStateDescription pci_bridge_dev_vmstate = {
-    .name = "pci_bridge",
-    .fields = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(bridge.dev, PCIBridgeDev),
-        SHPC_VMSTATE(bridge.dev.shpc, PCIBridgeDev),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    k->init = pci_bridge_dev_initfn;
-    k->exit = pci_bridge_dev_exitfn;
-    k->config_write = pci_bridge_dev_write_config;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT;
-    k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE;
-    k->class_id = PCI_CLASS_BRIDGE_PCI;
-    k->is_bridge = 1,
-    dc->desc = "Standard PCI Bridge";
-    dc->reset = qdev_pci_bridge_dev_reset;
-    dc->props = pci_bridge_dev_properties;
-    dc->vmsd = &pci_bridge_dev_vmstate;
-}
-
-static const TypeInfo pci_bridge_dev_info = {
-    .name = "pci-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIBridgeDev),
-    .class_init = pci_bridge_dev_class_init,
-};
-
-static void pci_bridge_dev_register(void)
-{
-    type_register_static(&pci_bridge_dev_info);
-}
-
-type_init(pci_bridge_dev_register);
diff --git a/hw/pci/bridge/xio3130_downstream.c b/hw/pci/bridge/xio3130_downstream.c
deleted file mode 100644 (file)
index b868f56..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * x3130_downstream.c
- * TI X3130 pci express downstream port switch
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * 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 of the License, or
- * (at your option) any later version.
- *
- * 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/>.
- */
-
-#include "hw/pci/pci_ids.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/pcie.h"
-#include "hw/xio3130_downstream.h"
-
-#define PCI_DEVICE_ID_TI_XIO3130D       0x8233  /* downstream port */
-#define XIO3130_REVISION                0x1
-#define XIO3130_MSI_OFFSET              0x70
-#define XIO3130_MSI_SUPPORTED_FLAGS     PCI_MSI_FLAGS_64BIT
-#define XIO3130_MSI_NR_VECTOR           1
-#define XIO3130_SSVID_OFFSET            0x80
-#define XIO3130_SSVID_SVID              0
-#define XIO3130_SSVID_SSID              0
-#define XIO3130_EXP_OFFSET              0x90
-#define XIO3130_AER_OFFSET              0x100
-
-static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address,
-                                         uint32_t val, int len)
-{
-    pci_bridge_write_config(d, address, val, len);
-    pcie_cap_flr_write_config(d, address, val, len);
-    pcie_cap_slot_write_config(d, address, val, len);
-    pcie_aer_write_config(d, address, val, len);
-}
-
-static void xio3130_downstream_reset(DeviceState *qdev)
-{
-    PCIDevice *d = PCI_DEVICE(qdev);
-
-    pcie_cap_deverr_reset(d);
-    pcie_cap_slot_reset(d);
-    pcie_cap_ari_reset(d);
-    pci_bridge_reset(qdev);
-}
-
-static int xio3130_downstream_initfn(PCIDevice *d)
-{
-    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
-    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
-    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
-    int rc;
-
-    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
-    if (rc < 0) {
-        return rc;
-    }
-
-    pcie_port_init_reg(d);
-
-    rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
-                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
-                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
-                               XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
-                       p->port);
-    if (rc < 0) {
-        goto err_msi;
-    }
-    pcie_cap_flr_init(d);
-    pcie_cap_deverr_init(d);
-    pcie_cap_slot_init(d, s->slot);
-    pcie_chassis_create(s->chassis);
-    rc = pcie_chassis_add_slot(s);
-    if (rc < 0) {
-        goto err_pcie_cap;
-    }
-    pcie_cap_ari_init(d);
-    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
-    if (rc < 0) {
-        goto err;
-    }
-
-    return 0;
-
-err:
-    pcie_chassis_del_slot(s);
-err_pcie_cap:
-    pcie_cap_exit(d);
-err_msi:
-    msi_uninit(d);
-err_bridge:
-    pci_bridge_exitfn(d);
-    return rc;
-}
-
-static void xio3130_downstream_exitfn(PCIDevice *d)
-{
-    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
-    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
-    PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
-
-    pcie_aer_exit(d);
-    pcie_chassis_del_slot(s);
-    pcie_cap_exit(d);
-    msi_uninit(d);
-    pci_bridge_exitfn(d);
-}
-
-PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
-                                  const char *bus_name, pci_map_irq_fn map_irq,
-                                  uint8_t port, uint8_t chassis,
-                                  uint16_t slot)
-{
-    PCIDevice *d;
-    PCIBridge *br;
-    DeviceState *qdev;
-
-    d = pci_create_multifunction(bus, devfn, multifunction,
-                                 "xio3130-downstream");
-    if (!d) {
-        return NULL;
-    }
-    br = DO_UPCAST(PCIBridge, dev, d);
-
-    qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
-    qdev_prop_set_uint8(qdev, "port", port);
-    qdev_prop_set_uint8(qdev, "chassis", chassis);
-    qdev_prop_set_uint16(qdev, "slot", slot);
-    qdev_init_nofail(qdev);
-
-    return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
-}
-
-static const VMStateDescription vmstate_xio3130_downstream = {
-    .name = "xio3130-express-downstream-port",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = pcie_cap_slot_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
-        VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
-                       vmstate_pcie_aer_log, PCIEAERLog),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property xio3130_downstream_properties[] = {
-    DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
-    DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
-    DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
-    DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
-    port.br.dev.exp.aer_log.log_max,
-    PCIE_AER_LOG_MAX_DEFAULT),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->is_express = 1;
-    k->is_bridge = 1;
-    k->config_write = xio3130_downstream_write_config;
-    k->init = xio3130_downstream_initfn;
-    k->exit = xio3130_downstream_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_TI;
-    k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
-    k->revision = XIO3130_REVISION;
-    dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
-    dc->reset = xio3130_downstream_reset;
-    dc->vmsd = &vmstate_xio3130_downstream;
-    dc->props = xio3130_downstream_properties;
-}
-
-static const TypeInfo xio3130_downstream_info = {
-    .name          = "xio3130-downstream",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIESlot),
-    .class_init    = xio3130_downstream_class_init,
-};
-
-static void xio3130_downstream_register_types(void)
-{
-    type_register_static(&xio3130_downstream_info);
-}
-
-type_init(xio3130_downstream_register_types)
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
diff --git a/hw/pci/bridge/xio3130_upstream.c b/hw/pci/bridge/xio3130_upstream.c
deleted file mode 100644 (file)
index cd5d97d..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * xio3130_upstream.c
- * TI X3130 pci express upstream port switch
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * 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 of the License, or
- * (at your option) any later version.
- *
- * 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/>.
- */
-
-#include "hw/pci/pci_ids.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/pcie.h"
-#include "hw/xio3130_upstream.h"
-
-#define PCI_DEVICE_ID_TI_XIO3130U       0x8232  /* upstream port */
-#define XIO3130_REVISION                0x2
-#define XIO3130_MSI_OFFSET              0x70
-#define XIO3130_MSI_SUPPORTED_FLAGS     PCI_MSI_FLAGS_64BIT
-#define XIO3130_MSI_NR_VECTOR           1
-#define XIO3130_SSVID_OFFSET            0x80
-#define XIO3130_SSVID_SVID              0
-#define XIO3130_SSVID_SSID              0
-#define XIO3130_EXP_OFFSET              0x90
-#define XIO3130_AER_OFFSET              0x100
-
-static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address,
-                                          uint32_t val, int len)
-{
-    pci_bridge_write_config(d, address, val, len);
-    pcie_cap_flr_write_config(d, address, val, len);
-    pcie_aer_write_config(d, address, val, len);
-}
-
-static void xio3130_upstream_reset(DeviceState *qdev)
-{
-    PCIDevice *d = PCI_DEVICE(qdev);
-
-    pci_bridge_reset(qdev);
-    pcie_cap_deverr_reset(d);
-}
-
-static int xio3130_upstream_initfn(PCIDevice *d)
-{
-    PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
-    PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
-    int rc;
-
-    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
-    if (rc < 0) {
-        return rc;
-    }
-
-    pcie_port_init_reg(d);
-
-    rc = msi_init(d, XIO3130_MSI_OFFSET, XIO3130_MSI_NR_VECTOR,
-                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT,
-                  XIO3130_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = pci_bridge_ssvid_init(d, XIO3130_SSVID_OFFSET,
-                               XIO3130_SSVID_SVID, XIO3130_SSVID_SSID);
-    if (rc < 0) {
-        goto err_bridge;
-    }
-    rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
-                       p->port);
-    if (rc < 0) {
-        goto err_msi;
-    }
-    pcie_cap_flr_init(d);
-    pcie_cap_deverr_init(d);
-    rc = pcie_aer_init(d, XIO3130_AER_OFFSET);
-    if (rc < 0) {
-        goto err;
-    }
-
-    return 0;
-
-err:
-    pcie_cap_exit(d);
-err_msi:
-    msi_uninit(d);
-err_bridge:
-    pci_bridge_exitfn(d);
-    return rc;
-}
-
-static void xio3130_upstream_exitfn(PCIDevice *d)
-{
-    pcie_aer_exit(d);
-    pcie_cap_exit(d);
-    msi_uninit(d);
-    pci_bridge_exitfn(d);
-}
-
-PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
-                             const char *bus_name, pci_map_irq_fn map_irq,
-                             uint8_t port)
-{
-    PCIDevice *d;
-    PCIBridge *br;
-    DeviceState *qdev;
-
-    d = pci_create_multifunction(bus, devfn, multifunction, "x3130-upstream");
-    if (!d) {
-        return NULL;
-    }
-    br = DO_UPCAST(PCIBridge, dev, d);
-
-    qdev = &br->dev.qdev;
-    pci_bridge_map_irq(br, bus_name, map_irq);
-    qdev_prop_set_uint8(qdev, "port", port);
-    qdev_init_nofail(qdev);
-
-    return DO_UPCAST(PCIEPort, br, br);
-}
-
-static const VMStateDescription vmstate_xio3130_upstream = {
-    .name = "xio3130-express-upstream-port",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_PCIE_DEVICE(br.dev, PCIEPort),
-        VMSTATE_STRUCT(br.dev.exp.aer_log, PCIEPort, 0, vmstate_pcie_aer_log,
-                       PCIEAERLog),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property xio3130_upstream_properties[] = {
-    DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
-    DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
-    PCIE_AER_LOG_MAX_DEFAULT),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->is_express = 1;
-    k->is_bridge = 1;
-    k->config_write = xio3130_upstream_write_config;
-    k->init = xio3130_upstream_initfn;
-    k->exit = xio3130_upstream_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_TI;
-    k->device_id = PCI_DEVICE_ID_TI_XIO3130U;
-    k->revision = XIO3130_REVISION;
-    dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
-    dc->reset = xio3130_upstream_reset;
-    dc->vmsd = &vmstate_xio3130_upstream;
-    dc->props = xio3130_upstream_properties;
-}
-
-static const TypeInfo xio3130_upstream_info = {
-    .name          = "x3130-upstream",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIEPort),
-    .class_init    = xio3130_upstream_class_init,
-};
-
-static void xio3130_upstream_register_types(void)
-{
-    type_register_static(&xio3130_upstream_info);
-}
-
-type_init(xio3130_upstream_register_types)
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
diff --git a/hw/pci/host/Makefile.objs b/hw/pci/host/Makefile.objs
deleted file mode 100644 (file)
index e1d6cce..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-common-obj-y += pam.o
-
-# PPC devices
-common-obj-$(CONFIG_PREP_PCI) += prep.o
-common-obj-$(CONFIG_GRACKLE_PCI) += grackle.o
-# NewWorld PowerMac
-common-obj-$(CONFIG_UNIN_PCI) += uninorth.o
-common-obj-$(CONFIG_DEC_PCI) += dec.o
-# PowerPC E500 boards
-common-obj-$(CONFIG_PPCE500_PCI) += ppce500.o
-
-# ARM devices
-common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
diff --git a/hw/pci/host/dec.c b/hw/pci/host/dec.c
deleted file mode 100644 (file)
index 6ec3d22..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * QEMU DEC 21154 PCI bridge
- *
- * Copyright (c) 2006-2007 Fabrice Bellard
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/dec_pci.h"
-#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "hw/pci/pci_bridge.h"
-#include "hw/pci/pci_bus.h"
-
-/* debug DEC */
-//#define DEBUG_DEC
-
-#ifdef DEBUG_DEC
-#define DEC_DPRINTF(fmt, ...)                               \
-    do { printf("DEC: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DEC_DPRINTF(fmt, ...)
-#endif
-
-#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
-
-typedef struct DECState {
-    PCIHostState parent_obj;
-} DECState;
-
-static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    return irq_num;
-}
-
-static int dec_pci_bridge_initfn(PCIDevice *pci_dev)
-{
-    return pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
-}
-
-static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = dec_pci_bridge_initfn;
-    k->exit = pci_bridge_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_DEC;
-    k->device_id = PCI_DEVICE_ID_DEC_21154;
-    k->config_write = pci_bridge_write_config;
-    k->is_bridge = 1;
-    dc->desc = "DEC 21154 PCI-PCI bridge";
-    dc->reset = pci_bridge_reset;
-    dc->vmsd = &vmstate_pci_device;
-}
-
-static const TypeInfo dec_21154_pci_bridge_info = {
-    .name          = "dec-21154-p2p-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIBridge),
-    .class_init    = dec_21154_pci_bridge_class_init,
-};
-
-PCIBus *pci_dec_21154_init(PCIBus *parent_bus, int devfn)
-{
-    PCIDevice *dev;
-    PCIBridge *br;
-
-    dev = pci_create_multifunction(parent_bus, devfn, false,
-                                   "dec-21154-p2p-bridge");
-    br = DO_UPCAST(PCIBridge, dev, dev);
-    pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
-    qdev_init_nofail(&dev->qdev);
-    return pci_bridge_get_sec_bus(br);
-}
-
-static int pci_dec_21154_device_init(SysBusDevice *dev)
-{
-    PCIHostState *phb;
-
-    phb = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
-                          dev, "pci-data-idx", 0x1000);
-    sysbus_init_mmio(dev, &phb->conf_mem);
-    sysbus_init_mmio(dev, &phb->data_mem);
-    return 0;
-}
-
-static int dec_21154_pci_host_init(PCIDevice *d)
-{
-    /* PCI2PCI bridge same values as PearPC - check this */
-    return 0;
-}
-
-static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = dec_21154_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_DEC;
-    k->device_id = PCI_DEVICE_ID_DEC_21154;
-    k->revision = 0x02;
-    k->class_id = PCI_CLASS_BRIDGE_PCI;
-    k->is_bridge = 1;
-}
-
-static const TypeInfo dec_21154_pci_host_info = {
-    .name          = "dec-21154",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = dec_21154_pci_host_class_init,
-};
-
-static void pci_dec_21154_device_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = pci_dec_21154_device_init;
-}
-
-static const TypeInfo pci_dec_21154_device_info = {
-    .name          = TYPE_DEC_21154,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(DECState),
-    .class_init    = pci_dec_21154_device_class_init,
-};
-
-static void dec_register_types(void)
-{
-    type_register_static(&pci_dec_21154_device_info);
-    type_register_static(&dec_21154_pci_host_info);
-    type_register_static(&dec_21154_pci_bridge_info);
-}
-
-type_init(dec_register_types)
diff --git a/hw/pci/host/grackle.c b/hw/pci/host/grackle.c
deleted file mode 100644 (file)
index 69344d9..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * QEMU Grackle PCI host (heathrow OldWorld PowerMac)
- *
- * Copyright (c) 2006-2007 Fabrice Bellard
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/pci/pci_host.h"
-#include "hw/ppc/mac.h"
-#include "hw/pci/pci.h"
-
-/* debug Grackle */
-//#define DEBUG_GRACKLE
-
-#ifdef DEBUG_GRACKLE
-#define GRACKLE_DPRINTF(fmt, ...)                               \
-    do { printf("GRACKLE: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define GRACKLE_DPRINTF(fmt, ...)
-#endif
-
-#define GRACKLE_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(GrackleState, (obj), TYPE_GRACKLE_PCI_HOST_BRIDGE)
-
-typedef struct GrackleState {
-    PCIHostState parent_obj;
-
-    MemoryRegion pci_mmio;
-    MemoryRegion pci_hole;
-} GrackleState;
-
-/* Don't know if this matches real hardware, but it agrees with OHW.  */
-static int pci_grackle_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    return (irq_num + (pci_dev->devfn >> 3)) & 3;
-}
-
-static void pci_grackle_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    GRACKLE_DPRINTF("set_irq num %d level %d\n", irq_num, level);
-    qemu_set_irq(pic[irq_num + 0x15], level);
-}
-
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    PCIHostState *phb;
-    GrackleState *d;
-
-    dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    phb = PCI_HOST_BRIDGE(dev);
-    d = GRACKLE_PCI_HOST_BRIDGE(dev);
-
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
-                             0x80000000ULL, 0x7e000000ULL);
-    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
-                                &d->pci_hole);
-
-    phb->bus = pci_register_bus(dev, "pci",
-                                pci_grackle_set_irq,
-                                pci_grackle_map_irq,
-                                pic,
-                                &d->pci_mmio,
-                                address_space_io,
-                                0, 4, TYPE_PCI_BUS);
-
-    pci_create_simple(phb->bus, 0, "grackle");
-
-    sysbus_mmio_map(s, 0, base);
-    sysbus_mmio_map(s, 1, base + 0x00200000);
-
-    return phb->bus;
-}
-
-static int pci_grackle_init_device(SysBusDevice *dev)
-{
-    PCIHostState *phb;
-
-    phb = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops,
-                          dev, "pci-data-idx", 0x1000);
-    sysbus_init_mmio(dev, &phb->conf_mem);
-    sysbus_init_mmio(dev, &phb->data_mem);
-
-    return 0;
-}
-
-static int grackle_pci_host_init(PCIDevice *d)
-{
-    d->config[0x09] = 0x01;
-    return 0;
-}
-
-static void grackle_pci_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    k->init      = grackle_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
-    k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106;
-    k->revision  = 0x00;
-    k->class_id  = PCI_CLASS_BRIDGE_HOST;
-    dc->no_user = 1;
-}
-
-static const TypeInfo grackle_pci_info = {
-    .name          = "grackle",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init = grackle_pci_class_init,
-};
-
-static void pci_grackle_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    k->init = pci_grackle_init_device;
-    dc->no_user = 1;
-}
-
-static const TypeInfo grackle_pci_host_info = {
-    .name          = TYPE_GRACKLE_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(GrackleState),
-    .class_init    = pci_grackle_class_init,
-};
-
-static void grackle_register_types(void)
-{
-    type_register_static(&grackle_pci_info);
-    type_register_static(&grackle_pci_host_info);
-}
-
-type_init(grackle_register_types)
diff --git a/hw/pci/host/pam.c b/hw/pci/host/pam.c
deleted file mode 100644 (file)
index 7181bd6..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * QEMU i440FX/PIIX3 PCI Bridge Emulation
- *
- * Copyright (c) 2006 Fabrice Bellard
- * Copyright (c) 2011 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- * Copyright (c) 2012 Jason Baron <jbaron@redhat.com>
- *
- * Split out from piix_pci.c
- *
- * 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 "sysemu/sysemu.h"
-#include "hw/pci-host/pam.h"
-
-void smram_update(MemoryRegion *smram_region, uint8_t smram,
-                  uint8_t smm_enabled)
-{
-    bool smram_enabled;
-
-    smram_enabled = ((smm_enabled && (smram & SMRAM_G_SMRAME)) ||
-                        (smram & SMRAM_D_OPEN));
-    memory_region_set_enabled(smram_region, !smram_enabled);
-}
-
-void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
-                   MemoryRegion *smram_region)
-{
-    uint8_t smm_enabled = (smm != 0);
-    if (*host_smm_enabled != smm_enabled) {
-        *host_smm_enabled = smm_enabled;
-        smram_update(smram_region, smram, *host_smm_enabled);
-    }
-}
-
-void init_pam(MemoryRegion *ram_memory, MemoryRegion *system_memory,
-              MemoryRegion *pci_address_space, PAMMemoryRegion *mem,
-              uint32_t start, uint32_t size)
-{
-    int i;
-
-    /* RAM */
-    memory_region_init_alias(&mem->alias[3], "pam-ram", ram_memory,
-                             start, size);
-    /* ROM (XXX: not quite correct) */
-    memory_region_init_alias(&mem->alias[1], "pam-rom", ram_memory,
-                             start, size);
-    memory_region_set_readonly(&mem->alias[1], true);
-
-    /* XXX: should distinguish read/write cases */
-    memory_region_init_alias(&mem->alias[0], "pam-pci", pci_address_space,
-                             start, size);
-    memory_region_init_alias(&mem->alias[2], "pam-pci", pci_address_space,
-                             start, size);
-
-    for (i = 0; i < 4; ++i) {
-        memory_region_set_enabled(&mem->alias[i], false);
-        memory_region_add_subregion_overlap(system_memory, start,
-                                            &mem->alias[i], 1);
-    }
-    mem->current = 0;
-}
-
-void pam_update(PAMMemoryRegion *pam, int idx, uint8_t val)
-{
-    assert(0 <= idx && idx <= 12);
-
-    memory_region_set_enabled(&pam->alias[pam->current], false);
-    pam->current = (val >> ((!(idx & 1)) * 4)) & PAM_ATTR_MASK;
-    memory_region_set_enabled(&pam->alias[pam->current], true);
-}
diff --git a/hw/pci/host/ppce500.c b/hw/pci/host/ppce500.c
deleted file mode 100644 (file)
index 5e7ad94..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * QEMU PowerPC E500 embedded processors pci controller emulation
- *
- * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Yu Liu,     <yu.liu@freescale.com>
- *
- * This file is derived from hw/ppc4xx_pci.c,
- * the copyright for that material belongs to the original owners.
- *
- * This 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 of the  License, or
- * (at your option) any later version.
- */
-
-#include "hw/hw.h"
-#include "hw/ppc/e500-ccsr.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "qemu/bswap.h"
-#include "hw/pci-host/ppce500.h"
-
-#ifdef DEBUG_PCI
-#define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
-#else
-#define pci_debug(fmt, ...)
-#endif
-
-#define PCIE500_CFGADDR       0x0
-#define PCIE500_CFGDATA       0x4
-#define PCIE500_REG_BASE      0xC00
-#define PCIE500_ALL_SIZE      0x1000
-#define PCIE500_REG_SIZE      (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
-
-#define PCIE500_PCI_IOLEN     0x10000ULL
-
-#define PPCE500_PCI_CONFIG_ADDR         0x0
-#define PPCE500_PCI_CONFIG_DATA         0x4
-#define PPCE500_PCI_INTACK              0x8
-
-#define PPCE500_PCI_OW1                 (0xC20 - PCIE500_REG_BASE)
-#define PPCE500_PCI_OW2                 (0xC40 - PCIE500_REG_BASE)
-#define PPCE500_PCI_OW3                 (0xC60 - PCIE500_REG_BASE)
-#define PPCE500_PCI_OW4                 (0xC80 - PCIE500_REG_BASE)
-#define PPCE500_PCI_IW3                 (0xDA0 - PCIE500_REG_BASE)
-#define PPCE500_PCI_IW2                 (0xDC0 - PCIE500_REG_BASE)
-#define PPCE500_PCI_IW1                 (0xDE0 - PCIE500_REG_BASE)
-
-#define PPCE500_PCI_GASKET_TIMR         (0xE20 - PCIE500_REG_BASE)
-
-#define PCI_POTAR               0x0
-#define PCI_POTEAR              0x4
-#define PCI_POWBAR              0x8
-#define PCI_POWAR               0x10
-
-#define PCI_PITAR               0x0
-#define PCI_PIWBAR              0x8
-#define PCI_PIWBEAR             0xC
-#define PCI_PIWAR               0x10
-
-#define PPCE500_PCI_NR_POBS     5
-#define PPCE500_PCI_NR_PIBS     3
-
-struct  pci_outbound {
-    uint32_t potar;
-    uint32_t potear;
-    uint32_t powbar;
-    uint32_t powar;
-};
-
-struct pci_inbound {
-    uint32_t pitar;
-    uint32_t piwbar;
-    uint32_t piwbear;
-    uint32_t piwar;
-};
-
-#define TYPE_PPC_E500_PCI_HOST_BRIDGE "e500-pcihost"
-
-#define PPC_E500_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PPCE500PCIState, (obj), TYPE_PPC_E500_PCI_HOST_BRIDGE)
-
-struct PPCE500PCIState {
-    PCIHostState parent_obj;
-
-    struct pci_outbound pob[PPCE500_PCI_NR_POBS];
-    struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
-    uint32_t gasket_time;
-    qemu_irq irq[4];
-    uint32_t first_slot;
-    /* mmio maps */
-    MemoryRegion container;
-    MemoryRegion iomem;
-    MemoryRegion pio;
-};
-
-#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
-#define PPC_E500_PCI_BRIDGE(obj) \
-    OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE)
-
-struct PPCE500PCIBridgeState {
-    /*< private >*/
-    PCIDevice parent;
-    /*< public >*/
-
-    MemoryRegion bar0;
-};
-
-typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState;
-typedef struct PPCE500PCIState PPCE500PCIState;
-
-static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    PPCE500PCIState *pci = opaque;
-    unsigned long win;
-    uint32_t value = 0;
-    int idx;
-
-    win = addr & 0xfe0;
-
-    switch (win) {
-    case PPCE500_PCI_OW1:
-    case PPCE500_PCI_OW2:
-    case PPCE500_PCI_OW3:
-    case PPCE500_PCI_OW4:
-        idx = (addr >> 5) & 0x7;
-        switch (addr & 0xC) {
-        case PCI_POTAR:
-            value = pci->pob[idx].potar;
-            break;
-        case PCI_POTEAR:
-            value = pci->pob[idx].potear;
-            break;
-        case PCI_POWBAR:
-            value = pci->pob[idx].powbar;
-            break;
-        case PCI_POWAR:
-            value = pci->pob[idx].powar;
-            break;
-        default:
-            break;
-        }
-        break;
-
-    case PPCE500_PCI_IW3:
-    case PPCE500_PCI_IW2:
-    case PPCE500_PCI_IW1:
-        idx = ((addr >> 5) & 0x3) - 1;
-        switch (addr & 0xC) {
-        case PCI_PITAR:
-            value = pci->pib[idx].pitar;
-            break;
-        case PCI_PIWBAR:
-            value = pci->pib[idx].piwbar;
-            break;
-        case PCI_PIWBEAR:
-            value = pci->pib[idx].piwbear;
-            break;
-        case PCI_PIWAR:
-            value = pci->pib[idx].piwar;
-            break;
-        default:
-            break;
-        };
-        break;
-
-    case PPCE500_PCI_GASKET_TIMR:
-        value = pci->gasket_time;
-        break;
-
-    default:
-        break;
-    }
-
-    pci_debug("%s: win:%lx(addr:" TARGET_FMT_plx ") -> value:%x\n", __func__,
-              win, addr, value);
-    return value;
-}
-
-static void pci_reg_write4(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    PPCE500PCIState *pci = opaque;
-    unsigned long win;
-    int idx;
-
-    win = addr & 0xfe0;
-
-    pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
-              __func__, (unsigned)value, win, addr);
-
-    switch (win) {
-    case PPCE500_PCI_OW1:
-    case PPCE500_PCI_OW2:
-    case PPCE500_PCI_OW3:
-    case PPCE500_PCI_OW4:
-        idx = (addr >> 5) & 0x7;
-        switch (addr & 0xC) {
-        case PCI_POTAR:
-            pci->pob[idx].potar = value;
-            break;
-        case PCI_POTEAR:
-            pci->pob[idx].potear = value;
-            break;
-        case PCI_POWBAR:
-            pci->pob[idx].powbar = value;
-            break;
-        case PCI_POWAR:
-            pci->pob[idx].powar = value;
-            break;
-        default:
-            break;
-        };
-        break;
-
-    case PPCE500_PCI_IW3:
-    case PPCE500_PCI_IW2:
-    case PPCE500_PCI_IW1:
-        idx = ((addr >> 5) & 0x3) - 1;
-        switch (addr & 0xC) {
-        case PCI_PITAR:
-            pci->pib[idx].pitar = value;
-            break;
-        case PCI_PIWBAR:
-            pci->pib[idx].piwbar = value;
-            break;
-        case PCI_PIWBEAR:
-            pci->pib[idx].piwbear = value;
-            break;
-        case PCI_PIWAR:
-            pci->pib[idx].piwar = value;
-            break;
-        default:
-            break;
-        };
-        break;
-
-    case PPCE500_PCI_GASKET_TIMR:
-        pci->gasket_time = value;
-        break;
-
-    default:
-        break;
-    };
-}
-
-static const MemoryRegionOps e500_pci_reg_ops = {
-    .read = pci_reg_read4,
-    .write = pci_reg_write4,
-    .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    int devno = pci_dev->devfn >> 3;
-    int ret;
-
-    ret = ppce500_pci_map_irq_slot(devno, irq_num);
-
-    pci_debug("%s: devfn %x irq %d -> %d  devno:%x\n", __func__,
-           pci_dev->devfn, irq_num, ret, devno);
-
-    return ret;
-}
-
-static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level);
-
-    qemu_set_irq(pic[irq_num], level);
-}
-
-static const VMStateDescription vmstate_pci_outbound = {
-    .name = "pci_outbound",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(potar, struct pci_outbound),
-        VMSTATE_UINT32(potear, struct pci_outbound),
-        VMSTATE_UINT32(powbar, struct pci_outbound),
-        VMSTATE_UINT32(powar, struct pci_outbound),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_pci_inbound = {
-    .name = "pci_inbound",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(pitar, struct pci_inbound),
-        VMSTATE_UINT32(piwbar, struct pci_inbound),
-        VMSTATE_UINT32(piwbear, struct pci_inbound),
-        VMSTATE_UINT32(piwar, struct pci_inbound),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_ppce500_pci = {
-    .name = "ppce500_pci",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
-                             vmstate_pci_outbound, struct pci_outbound),
-        VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
-                             vmstate_pci_outbound, struct pci_inbound),
-        VMSTATE_UINT32(gasket_time, PPCE500PCIState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-#include "exec/address-spaces.h"
-
-static int e500_pcihost_bridge_initfn(PCIDevice *d)
-{
-    PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d);
-    PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(),
-                                  "/e500-ccsr"));
-
-    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
-    d->config[PCI_HEADER_TYPE] =
-        (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
-        PCI_HEADER_TYPE_BRIDGE;
-
-    memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space,
-                             0, int128_get64(ccsr->ccsr_space.size));
-    pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
-
-    return 0;
-}
-
-static int e500_pcihost_initfn(SysBusDevice *dev)
-{
-    PCIHostState *h;
-    PPCE500PCIState *s;
-    PCIBus *b;
-    int i;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    h = PCI_HOST_BRIDGE(dev);
-    s = PPC_E500_PCI_HOST_BRIDGE(dev);
-
-    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
-    }
-
-    memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN);
-
-    b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, address_space_mem,
-                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
-    h->bus = b;
-
-    pci_create_simple(b, 0, "e500-host-bridge");
-
-    memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
-                          "pci-conf-idx", 4);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
-                          "pci-conf-data", 4);
-    memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
-                          "pci.reg", PCIE500_REG_SIZE);
-    memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
-    memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
-    memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
-    sysbus_init_mmio(dev, &s->container);
-    sysbus_init_mmio(dev, &s->pio);
-
-    return 0;
-}
-
-static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = e500_pcihost_bridge_initfn;
-    k->vendor_id = PCI_VENDOR_ID_FREESCALE;
-    k->device_id = PCI_DEVICE_ID_MPC8533E;
-    k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
-    dc->desc = "Host bridge";
-}
-
-static const TypeInfo e500_host_bridge_info = {
-    .name          = "e500-host-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PPCE500PCIBridgeState),
-    .class_init    = e500_host_bridge_class_init,
-};
-
-static Property pcihost_properties[] = {
-    DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void e500_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = e500_pcihost_initfn;
-    dc->props = pcihost_properties;
-    dc->vmsd = &vmstate_ppce500_pci;
-}
-
-static const TypeInfo e500_pcihost_info = {
-    .name          = TYPE_PPC_E500_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(PPCE500PCIState),
-    .class_init    = e500_pcihost_class_init,
-};
-
-static void e500_pci_register_types(void)
-{
-    type_register_static(&e500_pcihost_info);
-    type_register_static(&e500_host_bridge_info);
-}
-
-type_init(e500_pci_register_types)
diff --git a/hw/pci/host/prep.c b/hw/pci/host/prep.c
deleted file mode 100644 (file)
index 6130253..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * QEMU PREP PCI host
- *
- * Copyright (c) 2006 Fabrice Bellard
- * Copyright (c) 2011-2013 Andreas Färber
- *
- * 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/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_bus.h"
-#include "hw/pci/pci_host.h"
-#include "hw/i386/pc.h"
-#include "exec/address-spaces.h"
-
-#define TYPE_RAVEN_PCI_DEVICE "raven"
-#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
-
-#define RAVEN_PCI_DEVICE(obj) \
-    OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE)
-
-typedef struct RavenPCIState {
-    PCIDevice dev;
-} RavenPCIState;
-
-#define RAVEN_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
-
-typedef struct PRePPCIState {
-    PCIHostState parent_obj;
-
-    MemoryRegion intack;
-    qemu_irq irq[4];
-    PCIBus pci_bus;
-    RavenPCIState pci_dev;
-} PREPPCIState;
-
-static inline uint32_t PPC_PCIIO_config(hwaddr addr)
-{
-    int i;
-
-    for (i = 0; i < 11; i++) {
-        if ((addr & (1 << (11 + i))) != 0) {
-            break;
-        }
-    }
-    return (addr & 0x7ff) |  (i << 11);
-}
-
-static void ppc_pci_io_write(void *opaque, hwaddr addr,
-                             uint64_t val, unsigned int size)
-{
-    PREPPCIState *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
-}
-
-static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr,
-                                unsigned int size)
-{
-    PREPPCIState *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
-}
-
-static const MemoryRegionOps PPC_PCIIO_ops = {
-    .read = ppc_pci_io_read,
-    .write = ppc_pci_io_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static uint64_t ppc_intack_read(void *opaque, hwaddr addr,
-                                unsigned int size)
-{
-    return pic_read_irq(isa_pic);
-}
-
-static const MemoryRegionOps PPC_intack_ops = {
-    .read = ppc_intack_read,
-    .valid = {
-        .max_access_size = 1,
-    },
-};
-
-static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    return (irq_num + (pci_dev->devfn >> 3)) & 1;
-}
-
-static void prep_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    qemu_set_irq(pic[irq_num] , level);
-}
-
-static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(d);
-    PCIHostState *h = PCI_HOST_BRIDGE(dev);
-    PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
-    MemoryRegion *address_space_mem = get_system_memory();
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
-    }
-
-    pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4);
-
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s,
-                          "pci-conf-idx", 1);
-    sysbus_add_io(dev, 0xcf8, &h->conf_mem);
-    sysbus_init_ioports(&h->busdev, 0xcf8, 1);
-
-    memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s,
-                          "pci-conf-data", 1);
-    sysbus_add_io(dev, 0xcfc, &h->data_mem);
-    sysbus_init_ioports(&h->busdev, 0xcfc, 1);
-
-    memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
-    memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
-
-    memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1);
-    memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
-
-    /* TODO Remove once realize propagates to child devices. */
-    object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
-}
-
-static void raven_pcihost_initfn(Object *obj)
-{
-    PCIHostState *h = PCI_HOST_BRIDGE(obj);
-    PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *address_space_io = get_system_io();
-    DeviceState *pci_dev;
-
-    pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
-                        address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
-    h->bus = &s->pci_bus;
-
-    object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE);
-    pci_dev = DEVICE(&s->pci_dev);
-    qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
-    object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
-                            NULL);
-    qdev_prop_set_bit(pci_dev, "multifunction", false);
-}
-
-static int raven_init(PCIDevice *d)
-{
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x34] = 0x00; // capabilities_pointer
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_raven = {
-    .name = "raven",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .fields = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(dev, RavenPCIState),
-        VMSTATE_END_OF_LIST()
-    },
-};
-
-static void raven_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    k->init = raven_init;
-    k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
-    k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
-    k->revision = 0x00;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-    dc->desc = "PReP Host Bridge - Motorola Raven";
-    dc->vmsd = &vmstate_raven;
-    dc->no_user = 1;
-}
-
-static const TypeInfo raven_info = {
-    .name = TYPE_RAVEN_PCI_DEVICE,
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(RavenPCIState),
-    .class_init = raven_class_init,
-};
-
-static void raven_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->realize = raven_pcihost_realizefn;
-    dc->fw_name = "pci";
-    dc->no_user = 1;
-}
-
-static const TypeInfo raven_pcihost_info = {
-    .name = TYPE_RAVEN_PCI_HOST_BRIDGE,
-    .parent = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(PREPPCIState),
-    .instance_init = raven_pcihost_initfn,
-    .class_init = raven_pcihost_class_init,
-};
-
-static void raven_register_types(void)
-{
-    type_register_static(&raven_pcihost_info);
-    type_register_static(&raven_info);
-}
-
-type_init(raven_register_types)
diff --git a/hw/pci/host/uninorth.c b/hw/pci/host/uninorth.c
deleted file mode 100644 (file)
index fff235d..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * QEMU Uninorth PCI host (for all Mac99 and newer machines)
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * 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/hw.h"
-#include "hw/ppc/mac.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-
-/* debug UniNorth */
-//#define DEBUG_UNIN
-
-#ifdef DEBUG_UNIN
-#define UNIN_DPRINTF(fmt, ...)                                  \
-    do { printf("UNIN: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define UNIN_DPRINTF(fmt, ...)
-#endif
-
-static const int unin_irq_line[] = { 0x1b, 0x1c, 0x1d, 0x1e };
-
-#define TYPE_UNI_NORTH_PCI_HOST_BRIDGE "uni-north-pci-pcihost"
-#define TYPE_UNI_NORTH_AGP_HOST_BRIDGE "uni-north-agp-pcihost"
-#define TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE "uni-north-internal-pci-pcihost"
-#define TYPE_U3_AGP_HOST_BRIDGE "u3-agp-pcihost"
-
-#define UNI_NORTH_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_PCI_HOST_BRIDGE)
-#define UNI_NORTH_AGP_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_AGP_HOST_BRIDGE)
-#define UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINState, (obj), TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE)
-#define U3_AGP_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(UNINState, (obj), TYPE_U3_AGP_HOST_BRIDGE)
-
-typedef struct UNINState {
-    PCIHostState parent_obj;
-
-    MemoryRegion pci_mmio;
-    MemoryRegion pci_hole;
-} UNINState;
-
-static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    int retval;
-    int devfn = pci_dev->devfn & 0x00FFFFFF;
-
-    retval = (((devfn >> 11) & 0x1F) + irq_num) & 3;
-
-    return retval;
-}
-
-static void pci_unin_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    UNIN_DPRINTF("%s: setting INT %d = %d\n", __func__,
-                 unin_irq_line[irq_num], level);
-    qemu_set_irq(pic[unin_irq_line[irq_num]], level);
-}
-
-static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr)
-{
-    uint32_t retval;
-
-    if (reg & (1u << 31)) {
-        /* XXX OpenBIOS compatibility hack */
-        retval = reg | (addr & 3);
-    } else if (reg & 1) {
-        /* CFA1 style */
-        retval = (reg & ~7u) | (addr & 7);
-    } else {
-        uint32_t slot, func;
-
-        /* Grab CFA0 style values */
-        slot = ffs(reg & 0xfffff800) - 1;
-        func = (reg >> 8) & 7;
-
-        /* ... and then convert them to x86 format */
-        /* config pointer */
-        retval = (reg & (0xff - 7)) | (addr & 7);
-        /* slot */
-        retval |= slot << 11;
-        /* fn */
-        retval |= func << 8;
-    }
-
-
-    UNIN_DPRINTF("Converted config space accessor %08x/%08x -> %08x\n",
-                 reg, addr, retval);
-
-    return retval;
-}
-
-static void unin_data_write(void *opaque, hwaddr addr,
-                            uint64_t val, unsigned len)
-{
-    UNINState *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    UNIN_DPRINTF("write addr %" TARGET_FMT_plx " len %d val %"PRIx64"\n",
-                 addr, len, val);
-    pci_data_write(phb->bus,
-                   unin_get_config_reg(phb->config_reg, addr),
-                   val, len);
-}
-
-static uint64_t unin_data_read(void *opaque, hwaddr addr,
-                               unsigned len)
-{
-    UNINState *s = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    uint32_t val;
-
-    val = pci_data_read(phb->bus,
-                        unin_get_config_reg(phb->config_reg, addr),
-                        len);
-    UNIN_DPRINTF("read addr %" TARGET_FMT_plx " len %d val %x\n",
-                 addr, len, val);
-    return val;
-}
-
-static const MemoryRegionOps unin_data_ops = {
-    .read = unin_data_read,
-    .write = unin_data_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int pci_unin_main_init_device(SysBusDevice *dev)
-{
-    PCIHostState *h;
-
-    /* Use values found on a real PowerMac */
-    /* Uninorth main bus */
-    h = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
-                          "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &h->conf_mem);
-    sysbus_init_mmio(dev, &h->data_mem);
-
-    return 0;
-}
-
-
-static int pci_u3_agp_init_device(SysBusDevice *dev)
-{
-    PCIHostState *h;
-
-    /* Uninorth U3 AGP bus */
-    h = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &unin_data_ops, dev,
-                          "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &h->conf_mem);
-    sysbus_init_mmio(dev, &h->data_mem);
-
-    return 0;
-}
-
-static int pci_unin_agp_init_device(SysBusDevice *dev)
-{
-    PCIHostState *h;
-
-    /* Uninorth AGP bus */
-    h = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
-                          dev, "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &h->conf_mem);
-    sysbus_init_mmio(dev, &h->data_mem);
-    return 0;
-}
-
-static int pci_unin_internal_init_device(SysBusDevice *dev)
-{
-    PCIHostState *h;
-
-    /* Uninorth internal bus */
-    h = PCI_HOST_BRIDGE(dev);
-
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops,
-                          dev, "pci-conf-idx", 0x1000);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops,
-                          dev, "pci-conf-data", 0x1000);
-    sysbus_init_mmio(dev, &h->conf_mem);
-    sysbus_init_mmio(dev, &h->data_mem);
-    return 0;
-}
-
-PCIBus *pci_pmac_init(qemu_irq *pic,
-                      MemoryRegion *address_space_mem,
-                      MemoryRegion *address_space_io)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    PCIHostState *h;
-    UNINState *d;
-
-    /* Use values found on a real PowerMac */
-    /* Uninorth main bus */
-    dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    h = PCI_HOST_BRIDGE(s);
-    d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
-                             0x80000000ULL, 0x70000000ULL);
-    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
-                                &d->pci_hole);
-
-    h->bus = pci_register_bus(dev, "pci",
-                              pci_unin_set_irq, pci_unin_map_irq,
-                              pic,
-                              &d->pci_mmio,
-                              address_space_io,
-                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
-
-#if 0
-    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
-#endif
-
-    sysbus_mmio_map(s, 0, 0xf2800000);
-    sysbus_mmio_map(s, 1, 0xf2c00000);
-
-    /* DEC 21154 bridge */
-#if 0
-    /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
-    pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154");
-#endif
-
-    /* Uninorth AGP bus */
-    pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp");
-    dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, 0xf0800000);
-    sysbus_mmio_map(s, 1, 0xf0c00000);
-
-    /* Uninorth internal bus */
-#if 0
-    /* XXX: not needed for now */
-    pci_create_simple(h->bus, PCI_DEVFN(14, 0),
-                      "uni-north-internal-pci");
-    dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, 0xf4800000);
-    sysbus_mmio_map(s, 1, 0xf4c00000);
-#endif
-
-    return h->bus;
-}
-
-PCIBus *pci_pmac_u3_init(qemu_irq *pic,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    PCIHostState *h;
-    UNINState *d;
-
-    /* Uninorth AGP bus */
-
-    dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    h = PCI_HOST_BRIDGE(dev);
-    d = U3_AGP_HOST_BRIDGE(dev);
-
-    memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
-    memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio,
-                             0x80000000ULL, 0x70000000ULL);
-    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
-                                &d->pci_hole);
-
-    h->bus = pci_register_bus(dev, "pci",
-                              pci_unin_set_irq, pci_unin_map_irq,
-                              pic,
-                              &d->pci_mmio,
-                              address_space_io,
-                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
-
-    sysbus_mmio_map(s, 0, 0xf0800000);
-    sysbus_mmio_map(s, 1, 0xf0c00000);
-
-    pci_create_simple(h->bus, 11 << 3, "u3-agp");
-
-    return h->bus;
-}
-
-static int unin_main_pci_host_init(PCIDevice *d)
-{
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x34] = 0x00; // capabilities_pointer
-    return 0;
-}
-
-static int unin_agp_pci_host_init(PCIDevice *d)
-{
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    //    d->config[0x34] = 0x80; // capabilities_pointer
-    return 0;
-}
-
-static int u3_agp_pci_host_init(PCIDevice *d)
-{
-    /* cache line size */
-    d->config[0x0C] = 0x08;
-    /* latency timer */
-    d->config[0x0D] = 0x10;
-    return 0;
-}
-
-static int unin_internal_pci_host_init(PCIDevice *d)
-{
-    d->config[0x0C] = 0x08; // cache_line_size
-    d->config[0x0D] = 0x10; // latency_timer
-    d->config[0x34] = 0x00; // capabilities_pointer
-    return 0;
-}
-
-static void unin_main_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init      = unin_main_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_APPLE;
-    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI;
-    k->revision  = 0x00;
-    k->class_id  = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo unin_main_pci_host_info = {
-    .name = "uni-north-pci",
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init = unin_main_pci_host_class_init,
-};
-
-static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init      = u3_agp_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_APPLE;
-    k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP;
-    k->revision  = 0x00;
-    k->class_id  = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo u3_agp_pci_host_info = {
-    .name = "u3-agp",
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init = u3_agp_pci_host_class_init,
-};
-
-static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init      = unin_agp_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_APPLE;
-    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP;
-    k->revision  = 0x00;
-    k->class_id  = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo unin_agp_pci_host_info = {
-    .name = "uni-north-agp",
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init = unin_agp_pci_host_class_init,
-};
-
-static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init      = unin_internal_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_APPLE;
-    k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI;
-    k->revision  = 0x00;
-    k->class_id  = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo unin_internal_pci_host_info = {
-    .name = "uni-north-internal-pci",
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init = unin_internal_pci_host_class_init,
-};
-
-static void pci_unin_main_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = pci_unin_main_init_device;
-}
-
-static const TypeInfo pci_unin_main_info = {
-    .name          = TYPE_UNI_NORTH_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(UNINState),
-    .class_init    = pci_unin_main_class_init,
-};
-
-static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = pci_u3_agp_init_device;
-}
-
-static const TypeInfo pci_u3_agp_info = {
-    .name          = TYPE_U3_AGP_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(UNINState),
-    .class_init    = pci_u3_agp_class_init,
-};
-
-static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = pci_unin_agp_init_device;
-}
-
-static const TypeInfo pci_unin_agp_info = {
-    .name          = TYPE_UNI_NORTH_AGP_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(UNINState),
-    .class_init    = pci_unin_agp_class_init,
-};
-
-static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sbc->init = pci_unin_internal_init_device;
-}
-
-static const TypeInfo pci_unin_internal_info = {
-    .name          = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(UNINState),
-    .class_init    = pci_unin_internal_class_init,
-};
-
-static void unin_register_types(void)
-{
-    type_register_static(&unin_main_pci_host_info);
-    type_register_static(&u3_agp_pci_host_info);
-    type_register_static(&unin_agp_pci_host_info);
-    type_register_static(&unin_internal_pci_host_info);
-
-    type_register_static(&pci_unin_main_info);
-    type_register_static(&pci_u3_agp_info);
-    type_register_static(&pci_unin_agp_info);
-    type_register_static(&pci_unin_internal_info);
-}
-
-type_init(unin_register_types)
diff --git a/hw/pci/host/versatile.c b/hw/pci/host/versatile.c
deleted file mode 100644 (file)
index d67ca79..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * ARM Versatile/PB PCI host controller
- *
- * Copyright (c) 2006-2009 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
-    SysBusDevice busdev;
-    qemu_irq irq[4];
-    int realview;
-    MemoryRegion mem_config;
-    MemoryRegion mem_config2;
-    MemoryRegion isa;
-} PCIVPBState;
-
-static inline uint32_t vpb_pci_config_addr(hwaddr addr)
-{
-    return addr & 0xffffff;
-}
-
-static void pci_vpb_config_write(void *opaque, hwaddr addr,
-                                 uint64_t val, unsigned size)
-{
-    pci_data_write(opaque, vpb_pci_config_addr(addr), val, size);
-}
-
-static uint64_t pci_vpb_config_read(void *opaque, hwaddr addr,
-                                    unsigned size)
-{
-    uint32_t val;
-    val = pci_data_read(opaque, vpb_pci_config_addr(addr), size);
-    return val;
-}
-
-static const MemoryRegionOps pci_vpb_config_ops = {
-    .read = pci_vpb_config_read,
-    .write = pci_vpb_config_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
-{
-    return irq_num;
-}
-
-static void pci_vpb_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    qemu_set_irq(pic[irq_num], level);
-}
-
-static int pci_vpb_init(SysBusDevice *dev)
-{
-    PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
-    PCIBus *bus;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
-    }
-    bus = pci_register_bus(&dev->qdev, "pci",
-                           pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
-                           get_system_memory(), get_system_io(),
-                           PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
-
-    /* ??? Register memory space.  */
-
-    /* Our memory regions are:
-     * 0 : PCI self config window
-     * 1 : PCI config window
-     * 2 : PCI IO window (realview_pci only)
-     */
-    memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus,
-                          "pci-vpb-selfconfig", 0x1000000);
-    sysbus_init_mmio(dev, &s->mem_config);
-    memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus,
-                          "pci-vpb-config", 0x1000000);
-    sysbus_init_mmio(dev, &s->mem_config2);
-    if (s->realview) {
-        isa_mmio_setup(&s->isa, 0x0100000);
-        sysbus_init_mmio(dev, &s->isa);
-    }
-
-    pci_create_simple(bus, -1, "versatile_pci_host");
-    return 0;
-}
-
-static int pci_realview_init(SysBusDevice *dev)
-{
-    PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
-    s->realview = 1;
-    return pci_vpb_init(dev);
-}
-
-static int versatile_pci_host_init(PCIDevice *d)
-{
-    pci_set_word(d->config + PCI_STATUS,
-                PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM);
-    pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10);
-    return 0;
-}
-
-static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = versatile_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_XILINX;
-    k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30;
-    k->class_id = PCI_CLASS_PROCESSOR_CO;
-}
-
-static const TypeInfo versatile_pci_host_info = {
-    .name          = "versatile_pci_host",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = versatile_pci_host_class_init,
-};
-
-static void pci_vpb_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = pci_vpb_init;
-}
-
-static const TypeInfo pci_vpb_info = {
-    .name          = "versatile_pci",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PCIVPBState),
-    .class_init    = pci_vpb_class_init,
-};
-
-static void pci_realview_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = pci_realview_init;
-}
-
-static const TypeInfo pci_realview_info = {
-    .name          = "realview_pci",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PCIVPBState),
-    .class_init    = pci_realview_class_init,
-};
-
-static void versatile_pci_register_types(void)
-{
-    type_register_static(&pci_vpb_info);
-    type_register_static(&pci_realview_info);
-    type_register_static(&versatile_pci_host_info);
-}
-
-type_init(versatile_pci_register_types)
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
deleted file mode 100644 (file)
index f9e68c3..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * QEMU i440FX/PIIX3 PCI Bridge Emulation
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * 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/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "hw/isa/isa.h"
-#include "hw/sysbus.h"
-#include "qemu/range.h"
-#include "hw/xen/xen.h"
-#include "hw/pci-host/pam.h"
-#include "sysemu/sysemu.h"
-
-/*
- * I440FX chipset data sheet.
- * http://download.intel.com/design/chipsets/datashts/29054901.pdf
- */
-
-typedef struct I440FXState {
-    PCIHostState parent_obj;
-} I440FXState;
-
-#define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
-#define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
-#define XEN_PIIX_NUM_PIRQS      128ULL
-#define PIIX_PIRQC              0x60
-
-/*
- * Reset Control Register: PCI-accessible ISA-Compatible Register at address
- * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
- */
-#define RCR_IOPORT 0xcf9
-
-typedef struct PIIX3State {
-    PCIDevice dev;
-
-    /*
-     * bitmap to track pic levels.
-     * The pic level is the logical OR of all the PCI irqs mapped to it
-     * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
-     *
-     * PIRQ is mapped to PIC pins, we track it by
-     * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
-     * pic_irq * PIIX_NUM_PIRQS + pirq
-     */
-#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
-#error "unable to encode pic state in 64bit in pic_levels."
-#endif
-    uint64_t pic_levels;
-
-    qemu_irq *pic;
-
-    /* This member isn't used. Just for save/load compatibility */
-    int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
-
-    /* Reset Control Register contents */
-    uint8_t rcr;
-
-    /* IO memory region for Reset Control Register (RCR_IOPORT) */
-    MemoryRegion rcr_mem;
-} PIIX3State;
-
-#define TYPE_I440FX_PCI_DEVICE "i440FX"
-#define I440FX_PCI_DEVICE(obj) \
-    OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
-
-struct PCII440FXState {
-    PCIDevice dev;
-    MemoryRegion *system_memory;
-    MemoryRegion *pci_address_space;
-    MemoryRegion *ram_memory;
-    MemoryRegion pci_hole;
-    MemoryRegion pci_hole_64bit;
-    PAMMemoryRegion pam_regions[13];
-    MemoryRegion smram_region;
-    uint8_t smm_enabled;
-};
-
-
-#define I440FX_PAM      0x59
-#define I440FX_PAM_SIZE 7
-#define I440FX_SMRAM    0x72
-
-static void piix3_set_irq(void *opaque, int pirq, int level);
-static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx);
-static void piix3_write_config_xen(PCIDevice *dev,
-                               uint32_t address, uint32_t val, int len);
-
-/* return the global irq number corresponding to a given device irq
-   pin. We could also use the bus number to have a more precise
-   mapping. */
-static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
-{
-    int slot_addend;
-    slot_addend = (pci_dev->devfn >> 3) - 1;
-    return (pci_intx + slot_addend) & 3;
-}
-
-static void i440fx_update_memory_mappings(PCII440FXState *d)
-{
-    int i;
-
-    memory_region_transaction_begin();
-    for (i = 0; i < 13; i++) {
-        pam_update(&d->pam_regions[i], i,
-                   d->dev.config[I440FX_PAM + ((i + 1) / 2)]);
-    }
-    smram_update(&d->smram_region, d->dev.config[I440FX_SMRAM], d->smm_enabled);
-    memory_region_transaction_commit();
-}
-
-static void i440fx_set_smm(int val, void *arg)
-{
-    PCII440FXState *d = arg;
-
-    memory_region_transaction_begin();
-    smram_set_smm(&d->smm_enabled, val, d->dev.config[I440FX_SMRAM],
-                  &d->smram_region);
-    memory_region_transaction_commit();
-}
-
-
-static void i440fx_write_config(PCIDevice *dev,
-                                uint32_t address, uint32_t val, int len)
-{
-    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
-
-    /* XXX: implement SMRAM.D_LOCK */
-    pci_default_write_config(dev, address, val, len);
-    if (ranges_overlap(address, len, I440FX_PAM, I440FX_PAM_SIZE) ||
-        range_covers_byte(address, len, I440FX_SMRAM)) {
-        i440fx_update_memory_mappings(d);
-    }
-}
-
-static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
-{
-    PCII440FXState *d = opaque;
-    int ret, i;
-
-    ret = pci_device_load(&d->dev, f);
-    if (ret < 0)
-        return ret;
-    i440fx_update_memory_mappings(d);
-    qemu_get_8s(f, &d->smm_enabled);
-
-    if (version_id == 2) {
-        for (i = 0; i < PIIX_NUM_PIRQS; i++) {
-            qemu_get_be32(f); /* dummy load for compatibility */
-        }
-    }
-
-    return 0;
-}
-
-static int i440fx_post_load(void *opaque, int version_id)
-{
-    PCII440FXState *d = opaque;
-
-    i440fx_update_memory_mappings(d);
-    return 0;
-}
-
-static const VMStateDescription vmstate_i440fx = {
-    .name = "I440FX",
-    .version_id = 3,
-    .minimum_version_id = 3,
-    .minimum_version_id_old = 1,
-    .load_state_old = i440fx_load_old,
-    .post_load = i440fx_post_load,
-    .fields      = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(dev, PCII440FXState),
-        VMSTATE_UINT8(smm_enabled, PCII440FXState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int i440fx_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, 0xcf8, &s->conf_mem);
-    sysbus_init_ioports(&s->busdev, 0xcf8, 4);
-
-    memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s,
-                          "pci-conf-data", 4);
-    sysbus_add_io(dev, 0xcfc, &s->data_mem);
-    sysbus_init_ioports(&s->busdev, 0xcfc, 4);
-
-    return 0;
-}
-
-static int i440fx_initfn(PCIDevice *dev)
-{
-    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
-
-    d->dev.config[I440FX_SMRAM] = 0x02;
-
-    cpu_smm_register(&i440fx_set_smm, d);
-    return 0;
-}
-
-static PCIBus *i440fx_common_init(const char *device_name,
-                                  PCII440FXState **pi440fx_state,
-                                  int *piix3_devfn,
-                                  ISABus **isa_bus, qemu_irq *pic,
-                                  MemoryRegion *address_space_mem,
-                                  MemoryRegion *address_space_io,
-                                  ram_addr_t ram_size,
-                                  hwaddr pci_hole_start,
-                                  hwaddr pci_hole_size,
-                                  hwaddr pci_hole64_start,
-                                  hwaddr pci_hole64_size,
-                                  MemoryRegion *pci_address_space,
-                                  MemoryRegion *ram_memory)
-{
-    DeviceState *dev;
-    PCIBus *b;
-    PCIDevice *d;
-    PCIHostState *s;
-    PIIX3State *piix3;
-    PCII440FXState *f;
-    unsigned i;
-
-    dev = qdev_create(NULL, "i440FX-pcihost");
-    s = PCI_HOST_BRIDGE(dev);
-    b = pci_bus_new(dev, NULL, pci_address_space,
-                    address_space_io, 0, TYPE_PCI_BUS);
-    s->bus = b;
-    object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
-    qdev_init_nofail(dev);
-
-    d = pci_create_simple(b, 0, device_name);
-    *pi440fx_state = I440FX_PCI_DEVICE(d);
-    f = *pi440fx_state;
-    f->system_memory = address_space_mem;
-    f->pci_address_space = pci_address_space;
-    f->ram_memory = ram_memory;
-    memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space,
-                             pci_hole_start, pci_hole_size);
-    memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole);
-    memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64",
-                             f->pci_address_space,
-                             pci_hole64_start, pci_hole64_size);
-    if (pci_hole64_size) {
-        memory_region_add_subregion(f->system_memory, pci_hole64_start,
-                                    &f->pci_hole_64bit);
-    }
-    memory_region_init_alias(&f->smram_region, "smram-region",
-                             f->pci_address_space, 0xa0000, 0x20000);
-    memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
-                                        &f->smram_region, 1);
-    memory_region_set_enabled(&f->smram_region, false);
-    init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
-             &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
-    for (i = 0; i < 12; ++i) {
-        init_pam(f->ram_memory, f->system_memory, f->pci_address_space,
-                 &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
-                 PAM_EXPAN_SIZE);
-    }
-
-    /* Xen supports additional interrupt routes from the PCI devices to
-     * the IOAPIC: the four pins of each PCI device on the bus are also
-     * connected to the IOAPIC directly.
-     * These additional routes can be discovered through ACPI. */
-    if (xen_enabled()) {
-        piix3 = DO_UPCAST(PIIX3State, dev,
-                pci_create_simple_multifunction(b, -1, true, "PIIX3-xen"));
-        pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
-                piix3, XEN_PIIX_NUM_PIRQS);
-    } else {
-        piix3 = DO_UPCAST(PIIX3State, dev,
-                pci_create_simple_multifunction(b, -1, true, "PIIX3"));
-        pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3,
-                PIIX_NUM_PIRQS);
-        pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
-    }
-    piix3->pic = pic;
-    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
-
-    *piix3_devfn = piix3->dev.devfn;
-
-    ram_size = ram_size / 8 / 1024 / 1024;
-    if (ram_size > 255)
-        ram_size = 255;
-    (*pi440fx_state)->dev.config[0x57]=ram_size;
-
-    i440fx_update_memory_mappings(f);
-
-    return b;
-}
-
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    ISABus **isa_bus, qemu_irq *pic,
-                    MemoryRegion *address_space_mem,
-                    MemoryRegion *address_space_io,
-                    ram_addr_t ram_size,
-                    hwaddr pci_hole_start,
-                    hwaddr pci_hole_size,
-                    hwaddr pci_hole64_start,
-                    hwaddr pci_hole64_size,
-                    MemoryRegion *pci_memory, MemoryRegion *ram_memory)
-
-{
-    PCIBus *b;
-
-    b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
-                           piix3_devfn, isa_bus, pic,
-                           address_space_mem, address_space_io, ram_size,
-                           pci_hole_start, pci_hole_size,
-                           pci_hole64_start, pci_hole64_size,
-                           pci_memory, ram_memory);
-    return b;
-}
-
-/* PIIX3 PCI to ISA bridge */
-static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
-{
-    qemu_set_irq(piix3->pic[pic_irq],
-                 !!(piix3->pic_levels &
-                    (((1ULL << PIIX_NUM_PIRQS) - 1) <<
-                     (pic_irq * PIIX_NUM_PIRQS))));
-}
-
-static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
-{
-    int pic_irq;
-    uint64_t mask;
-
-    pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
-    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
-        return;
-    }
-
-    mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
-    piix3->pic_levels &= ~mask;
-    piix3->pic_levels |= mask * !!level;
-
-    piix3_set_irq_pic(piix3, pic_irq);
-}
-
-static void piix3_set_irq(void *opaque, int pirq, int level)
-{
-    PIIX3State *piix3 = opaque;
-    piix3_set_irq_level(piix3, pirq, level);
-}
-
-static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
-{
-    PIIX3State *piix3 = opaque;
-    int irq = piix3->dev.config[PIIX_PIRQC + pin];
-    PCIINTxRoute route;
-
-    if (irq < PIIX_NUM_PIC_IRQS) {
-        route.mode = PCI_INTX_ENABLED;
-        route.irq = irq;
-    } else {
-        route.mode = PCI_INTX_DISABLED;
-        route.irq = -1;
-    }
-    return route;
-}
-
-/* irq routing is changed. so rebuild bitmap */
-static void piix3_update_irq_levels(PIIX3State *piix3)
-{
-    int pirq;
-
-    piix3->pic_levels = 0;
-    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
-        piix3_set_irq_level(piix3, pirq,
-                            pci_bus_get_irq_level(piix3->dev.bus, pirq));
-    }
-}
-
-static void piix3_write_config(PCIDevice *dev,
-                               uint32_t address, uint32_t val, int len)
-{
-    pci_default_write_config(dev, address, val, len);
-    if (ranges_overlap(address, len, PIIX_PIRQC, 4)) {
-        PIIX3State *piix3 = DO_UPCAST(PIIX3State, dev, dev);
-        int pic_irq;
-
-        pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
-        piix3_update_irq_levels(piix3);
-        for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
-            piix3_set_irq_pic(piix3, pic_irq);
-        }
-    }
-}
-
-static void piix3_write_config_xen(PCIDevice *dev,
-                               uint32_t address, uint32_t val, int len)
-{
-    xen_piix_pci_write_config_client(address, val, len);
-    piix3_write_config(dev, address, val, len);
-}
-
-static void piix3_reset(void *opaque)
-{
-    PIIX3State *d = opaque;
-    uint8_t *pci_conf = d->dev.config;
-
-    pci_conf[0x04] = 0x07; /* master, memory and I/O */
-    pci_conf[0x05] = 0x00;
-    pci_conf[0x06] = 0x00;
-    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
-    pci_conf[0x4c] = 0x4d;
-    pci_conf[0x4e] = 0x03;
-    pci_conf[0x4f] = 0x00;
-    pci_conf[0x60] = 0x80;
-    pci_conf[0x61] = 0x80;
-    pci_conf[0x62] = 0x80;
-    pci_conf[0x63] = 0x80;
-    pci_conf[0x69] = 0x02;
-    pci_conf[0x70] = 0x80;
-    pci_conf[0x76] = 0x0c;
-    pci_conf[0x77] = 0x0c;
-    pci_conf[0x78] = 0x02;
-    pci_conf[0x79] = 0x00;
-    pci_conf[0x80] = 0x00;
-    pci_conf[0x82] = 0x00;
-    pci_conf[0xa0] = 0x08;
-    pci_conf[0xa2] = 0x00;
-    pci_conf[0xa3] = 0x00;
-    pci_conf[0xa4] = 0x00;
-    pci_conf[0xa5] = 0x00;
-    pci_conf[0xa6] = 0x00;
-    pci_conf[0xa7] = 0x00;
-    pci_conf[0xa8] = 0x0f;
-    pci_conf[0xaa] = 0x00;
-    pci_conf[0xab] = 0x00;
-    pci_conf[0xac] = 0x00;
-    pci_conf[0xae] = 0x00;
-
-    d->pic_levels = 0;
-    d->rcr = 0;
-}
-
-static int piix3_post_load(void *opaque, int version_id)
-{
-    PIIX3State *piix3 = opaque;
-    piix3_update_irq_levels(piix3);
-    return 0;
-}
-
-static void piix3_pre_save(void *opaque)
-{
-    int i;
-    PIIX3State *piix3 = opaque;
-
-    for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
-        piix3->pci_irq_levels_vmstate[i] =
-            pci_bus_get_irq_level(piix3->dev.bus, i);
-    }
-}
-
-static bool piix3_rcr_needed(void *opaque)
-{
-    PIIX3State *piix3 = opaque;
-
-    return (piix3->rcr != 0);
-}
-
-static const VMStateDescription vmstate_piix3_rcr = {
-    .name = "PIIX3/rcr",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT8(rcr, PIIX3State),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_piix3 = {
-    .name = "PIIX3",
-    .version_id = 3,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .post_load = piix3_post_load,
-    .pre_save = piix3_pre_save,
-    .fields      = (VMStateField[]) {
-        VMSTATE_PCI_DEVICE(dev, PIIX3State),
-        VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
-                              PIIX_NUM_PIRQS, 3),
-        VMSTATE_END_OF_LIST()
-    },
-    .subsections = (VMStateSubsection[]) {
-        {
-            .vmsd = &vmstate_piix3_rcr,
-            .needed = piix3_rcr_needed,
-        },
-        { 0 }
-    }
-};
-
-
-static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
-{
-    PIIX3State *d = opaque;
-
-    if (val & 4) {
-        qemu_system_reset_request();
-        return;
-    }
-    d->rcr = val & 2; /* keep System Reset type only */
-}
-
-static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
-{
-    PIIX3State *d = opaque;
-
-    return d->rcr;
-}
-
-static const MemoryRegionOps rcr_ops = {
-    .read = rcr_read,
-    .write = rcr_write,
-    .endianness = DEVICE_LITTLE_ENDIAN
-};
-
-static int piix3_initfn(PCIDevice *dev)
-{
-    PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
-
-    isa_bus_new(DEVICE(d), pci_address_space_io(dev));
-
-    memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
-    memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
-                                        &d->rcr_mem, 1);
-
-    qemu_register_reset(piix3_reset, d);
-    return 0;
-}
-
-static void piix3_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    dc->desc        = "ISA bridge";
-    dc->vmsd        = &vmstate_piix3;
-    dc->no_user     = 1,
-    k->no_hotplug   = 1;
-    k->init         = piix3_initfn;
-    k->config_write = piix3_write_config;
-    k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
-    k->class_id     = PCI_CLASS_BRIDGE_ISA;
-}
-
-static const TypeInfo piix3_info = {
-    .name          = "PIIX3",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PIIX3State),
-    .class_init    = piix3_class_init,
-};
-
-static void piix3_xen_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    dc->desc        = "ISA bridge";
-    dc->vmsd        = &vmstate_piix3;
-    dc->no_user     = 1;
-    k->no_hotplug   = 1;
-    k->init         = piix3_initfn;
-    k->config_write = piix3_write_config_xen;
-    k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
-    k->class_id     = PCI_CLASS_BRIDGE_ISA;
-};
-
-static const TypeInfo piix3_xen_info = {
-    .name          = "PIIX3-xen",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PIIX3State),
-    .class_init    = piix3_xen_class_init,
-};
-
-static void i440fx_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->no_hotplug = 1;
-    k->init = i440fx_initfn;
-    k->config_write = i440fx_write_config;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_82441;
-    k->revision = 0x02;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-    dc->desc = "Host bridge";
-    dc->no_user = 1;
-    dc->vmsd = &vmstate_i440fx;
-}
-
-static const TypeInfo i440fx_info = {
-    .name          = TYPE_I440FX_PCI_DEVICE,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCII440FXState),
-    .class_init    = i440fx_class_init,
-};
-
-static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = i440fx_pcihost_initfn;
-    dc->fw_name = "pci";
-    dc->no_user = 1;
-}
-
-static const TypeInfo i440fx_pcihost_info = {
-    .name          = "i440FX-pcihost",
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(I440FXState),
-    .class_init    = i440fx_pcihost_class_init,
-};
-
-static void i440fx_register_types(void)
-{
-    type_register_static(&i440fx_info);
-    type_register_static(&piix3_info);
-    type_register_static(&piix3_xen_info);
-    type_register_static(&i440fx_pcihost_info);
-}
-
-type_init(i440fx_register_types)
index 1e24b582826ae4363158859f1fcb32f0e728aa8e..70342c28ec5929ffde10e3c5ad6c488701fa693f 100644 (file)
@@ -1,8 +1,5 @@
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr_pci.o
 obj-$(CONFIG_PSERIES) += spapr_nvram.o
-# PowerPC 4xx boards
-obj-y += ppc4xx_pci.o
 # PowerPC OpenPIC
 obj-y += openpic.o
 
@@ -13,8 +10,10 @@ obj-y += ppc.o ppc_booke.o
 # IBM pSeries (sPAPR)
 obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o
 obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
+obj-y += ppc4xx_pci.o
 # PReP
 obj-y += prep.o
 # OldWorld PowerMac
diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c
new file mode 100644 (file)
index 0000000..599539b
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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/>.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+/* This file implements emulation of the 32-bit PCI controller found in some
+ * 4xx SoCs, such as the 440EP. */
+
+#include "hw/hw.h"
+#include "hw/ppc/ppc.h"
+#include "hw/ppc/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "exec/address-spaces.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif /* DEBUG */
+
+struct PCIMasterMap {
+    uint32_t la;
+    uint32_t ma;
+    uint32_t pcila;
+    uint32_t pciha;
+};
+
+struct PCITargetMap {
+    uint32_t ms;
+    uint32_t la;
+};
+
+#define PPC4xx_PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE)
+
+#define PPC4xx_PCI_NR_PMMS 3
+#define PPC4xx_PCI_NR_PTMS 2
+
+struct PPC4xxPCIState {
+    PCIHostState parent_obj;
+
+    struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
+    struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
+    qemu_irq irq[4];
+
+    MemoryRegion container;
+    MemoryRegion iomem;
+};
+typedef struct PPC4xxPCIState PPC4xxPCIState;
+
+#define PCIC0_CFGADDR       0x0
+#define PCIC0_CFGDATA       0x4
+
+/* PLB Memory Map (PMM) registers specify which PLB addresses are translated to
+ * PCI accesses. */
+#define PCIL0_PMM0LA        0x0
+#define PCIL0_PMM0MA        0x4
+#define PCIL0_PMM0PCILA     0x8
+#define PCIL0_PMM0PCIHA     0xc
+#define PCIL0_PMM1LA        0x10
+#define PCIL0_PMM1MA        0x14
+#define PCIL0_PMM1PCILA     0x18
+#define PCIL0_PMM1PCIHA     0x1c
+#define PCIL0_PMM2LA        0x20
+#define PCIL0_PMM2MA        0x24
+#define PCIL0_PMM2PCILA     0x28
+#define PCIL0_PMM2PCIHA     0x2c
+
+/* PCI Target Map (PTM) registers specify which PCI addresses are translated to
+ * PLB accesses. */
+#define PCIL0_PTM1MS        0x30
+#define PCIL0_PTM1LA        0x34
+#define PCIL0_PTM2MS        0x38
+#define PCIL0_PTM2LA        0x3c
+#define PCI_REG_BASE        0x800000
+#define PCI_REG_SIZE        0x40
+
+#define PCI_ALL_SIZE        (PCI_REG_BASE + PCI_REG_SIZE)
+
+static uint64_t pci4xx_cfgaddr_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    PPC4xxPCIState *ppc4xx_pci = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
+
+    return phb->config_reg;
+}
+
+static void pci4xx_cfgaddr_write(void *opaque, hwaddr addr,
+                                  uint64_t value, unsigned size)
+{
+    PPC4xxPCIState *ppc4xx_pci = opaque;
+    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
+
+    phb->config_reg = value & ~0x3;
+}
+
+static const MemoryRegionOps pci4xx_cfgaddr_ops = {
+    .read = pci4xx_cfgaddr_read,
+    .write = pci4xx_cfgaddr_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset,
+                                  uint64_t value, unsigned size)
+{
+    struct PPC4xxPCIState *pci = opaque;
+
+    /* We ignore all target attempts at PCI configuration, effectively
+     * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
+
+    switch (offset) {
+    case PCIL0_PMM0LA:
+        pci->pmm[0].la = value;
+        break;
+    case PCIL0_PMM0MA:
+        pci->pmm[0].ma = value;
+        break;
+    case PCIL0_PMM0PCIHA:
+        pci->pmm[0].pciha = value;
+        break;
+    case PCIL0_PMM0PCILA:
+        pci->pmm[0].pcila = value;
+        break;
+
+    case PCIL0_PMM1LA:
+        pci->pmm[1].la = value;
+        break;
+    case PCIL0_PMM1MA:
+        pci->pmm[1].ma = value;
+        break;
+    case PCIL0_PMM1PCIHA:
+        pci->pmm[1].pciha = value;
+        break;
+    case PCIL0_PMM1PCILA:
+        pci->pmm[1].pcila = value;
+        break;
+
+    case PCIL0_PMM2LA:
+        pci->pmm[2].la = value;
+        break;
+    case PCIL0_PMM2MA:
+        pci->pmm[2].ma = value;
+        break;
+    case PCIL0_PMM2PCIHA:
+        pci->pmm[2].pciha = value;
+        break;
+    case PCIL0_PMM2PCILA:
+        pci->pmm[2].pcila = value;
+        break;
+
+    case PCIL0_PTM1MS:
+        pci->ptm[0].ms = value;
+        break;
+    case PCIL0_PTM1LA:
+        pci->ptm[0].la = value;
+        break;
+    case PCIL0_PTM2MS:
+        pci->ptm[1].ms = value;
+        break;
+    case PCIL0_PTM2LA:
+        pci->ptm[1].la = value;
+        break;
+
+    default:
+        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
+               (unsigned long)offset);
+        break;
+    }
+}
+
+static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset,
+                                     unsigned size)
+{
+    struct PPC4xxPCIState *pci = opaque;
+    uint32_t value;
+
+    switch (offset) {
+    case PCIL0_PMM0LA:
+        value = pci->pmm[0].la;
+        break;
+    case PCIL0_PMM0MA:
+        value = pci->pmm[0].ma;
+        break;
+    case PCIL0_PMM0PCIHA:
+        value = pci->pmm[0].pciha;
+        break;
+    case PCIL0_PMM0PCILA:
+        value = pci->pmm[0].pcila;
+        break;
+
+    case PCIL0_PMM1LA:
+        value = pci->pmm[1].la;
+        break;
+    case PCIL0_PMM1MA:
+        value = pci->pmm[1].ma;
+        break;
+    case PCIL0_PMM1PCIHA:
+        value = pci->pmm[1].pciha;
+        break;
+    case PCIL0_PMM1PCILA:
+        value = pci->pmm[1].pcila;
+        break;
+
+    case PCIL0_PMM2LA:
+        value = pci->pmm[2].la;
+        break;
+    case PCIL0_PMM2MA:
+        value = pci->pmm[2].ma;
+        break;
+    case PCIL0_PMM2PCIHA:
+        value = pci->pmm[2].pciha;
+        break;
+    case PCIL0_PMM2PCILA:
+        value = pci->pmm[2].pcila;
+        break;
+
+    case PCIL0_PTM1MS:
+        value = pci->ptm[0].ms;
+        break;
+    case PCIL0_PTM1LA:
+        value = pci->ptm[0].la;
+        break;
+    case PCIL0_PTM2MS:
+        value = pci->ptm[1].ms;
+        break;
+    case PCIL0_PTM2LA:
+        value = pci->ptm[1].la;
+        break;
+
+    default:
+        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
+               (unsigned long)offset);
+        value = 0;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps pci_reg_ops = {
+    .read = ppc4xx_pci_reg_read4,
+    .write = ppc4xx_pci_reg_write4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ppc4xx_pci_reset(void *opaque)
+{
+    struct PPC4xxPCIState *pci = opaque;
+
+    memset(pci->pmm, 0, sizeof(pci->pmm));
+    memset(pci->ptm, 0, sizeof(pci->ptm));
+}
+
+/* On Bamboo, all pins from each slot are tied to a single board IRQ. This
+ * may need further refactoring for other boards. */
+static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot = pci_dev->devfn >> 3;
+
+    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
+            pci_dev->devfn, irq_num, slot);
+
+    return slot - 1;
+}
+
+static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pci_irqs = opaque;
+
+    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
+    if (irq_num < 0) {
+        fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);
+        return;
+    }
+    qemu_set_irq(pci_irqs[irq_num], level);
+}
+
+static const VMStateDescription vmstate_pci_master_map = {
+    .name = "pci_master_map",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(la, struct PCIMasterMap),
+        VMSTATE_UINT32(ma, struct PCIMasterMap),
+        VMSTATE_UINT32(pcila, struct PCIMasterMap),
+        VMSTATE_UINT32(pciha, struct PCIMasterMap),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_pci_target_map = {
+    .name = "pci_target_map",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(ms, struct PCITargetMap),
+        VMSTATE_UINT32(la, struct PCITargetMap),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_ppc4xx_pci = {
+    .name = "ppc4xx_pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
+                             vmstate_pci_master_map,
+                             struct PCIMasterMap),
+        VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
+                             vmstate_pci_target_map,
+                             struct PCITargetMap),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/* XXX Interrupt acknowledge cycles not supported. */
+static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
+{
+    PPC4xxPCIState *s;
+    PCIHostState *h;
+    PCIBus *b;
+    int i;
+
+    h = PCI_HOST_BRIDGE(dev);
+    s = PPC4xx_PCI_HOST_BRIDGE(dev);
+
+    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+
+    b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
+                         ppc4xx_pci_map_irq, s->irq, get_system_memory(),
+                         get_system_io(), 0, 4, TYPE_PCI_BUS);
+    h->bus = b;
+
+    pci_create_simple(b, 0, "ppc4xx-host-bridge");
+
+    /* XXX split into 2 memory regions, one for config space, one for regs */
+    memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE);
+    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h,
+                          "pci-conf-idx", 4);
+    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+                          "pci-conf-data", 4);
+    memory_region_init_io(&s->iomem, &pci_reg_ops, s,
+                          "pci.reg", PCI_REG_SIZE);
+    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
+    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
+    memory_region_add_subregion(&s->container, PCI_REG_BASE, &s->iomem);
+    sysbus_init_mmio(dev, &s->container);
+    qemu_register_reset(ppc4xx_pci_reset, s);
+
+    return 0;
+}
+
+static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->desc        = "Host bridge";
+    k->vendor_id    = PCI_VENDOR_ID_IBM;
+    k->device_id    = PCI_DEVICE_ID_IBM_440GX;
+    k->class_id     = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static const TypeInfo ppc4xx_host_bridge_info = {
+    .name          = "ppc4xx-host-bridge",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = ppc4xx_host_bridge_class_init,
+};
+
+static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init = ppc4xx_pcihost_initfn;
+    dc->vmsd = &vmstate_ppc4xx_pci;
+}
+
+static const TypeInfo ppc4xx_pcihost_info = {
+    .name          = TYPE_PPC4xx_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(PPC4xxPCIState),
+    .class_init    = ppc4xx_pcihost_class_init,
+};
+
+static void ppc4xx_pci_register_types(void)
+{
+    type_register_static(&ppc4xx_pcihost_info);
+    type_register_static(&ppc4xx_host_bridge_info);
+}
+
+type_init(ppc4xx_pci_register_types)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
new file mode 100644 (file)
index 0000000..62ff323
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * QEMU sPAPR PCI host originated from Uninorth PCI host
+ *
+ * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
+ * Copyright (C) 2011 David Gibson, IBM Corporation.
+ *
+ * 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/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ppc/spapr.h"
+#include "hw/pci-host/spapr.h"
+#include "exec/address-spaces.h"
+#include <libfdt.h>
+#include "trace.h"
+
+#include "hw/pci/pci_bus.h"
+
+/* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
+#define RTAS_QUERY_FN           0
+#define RTAS_CHANGE_FN          1
+#define RTAS_RESET_FN           2
+#define RTAS_CHANGE_MSI_FN      3
+#define RTAS_CHANGE_MSIX_FN     4
+
+/* Interrupt types to return on RTAS_CHANGE_* */
+#define RTAS_TYPE_MSI           1
+#define RTAS_TYPE_MSIX          2
+
+static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
+{
+    sPAPRPHBState *sphb;
+
+    QLIST_FOREACH(sphb, &spapr->phbs, list) {
+        if (sphb->buid != buid) {
+            continue;
+        }
+        return sphb;
+    }
+
+    return NULL;
+}
+
+static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
+                           uint32_t config_addr)
+{
+    sPAPRPHBState *sphb = find_phb(spapr, buid);
+    PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
+    BusState *bus = BUS(phb->bus);
+    BusChild *kid;
+    int devfn = (config_addr >> 8) & 0xFF;
+
+    if (!phb) {
+        return NULL;
+    }
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        PCIDevice *dev = (PCIDevice *)kid->child;
+        if (dev->devfn == devfn) {
+            return dev;
+        }
+    }
+
+    return NULL;
+}
+
+static uint32_t rtas_pci_cfgaddr(uint32_t arg)
+{
+    /* This handles the encoding of extended config space addresses */
+    return ((arg >> 20) & 0xf00) | (arg & 0xff);
+}
+
+static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+                                   uint32_t addr, uint32_t size,
+                                   target_ulong rets)
+{
+    PCIDevice *pci_dev;
+    uint32_t val;
+
+    if ((size != 1) && (size != 2) && (size != 4)) {
+        /* access must be 1, 2 or 4 bytes */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    pci_dev = find_dev(spapr, buid, addr);
+    addr = rtas_pci_cfgaddr(addr);
+
+    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+        /* Access must be to a valid device, within bounds and
+         * naturally aligned */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    val = pci_host_config_read_common(pci_dev, addr,
+                                      pci_config_size(pci_dev), size);
+
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, val);
+}
+
+static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
+                                     uint32_t token, uint32_t nargs,
+                                     target_ulong args,
+                                     uint32_t nret, target_ulong rets)
+{
+    uint64_t buid;
+    uint32_t size, addr;
+
+    if ((nargs != 4) || (nret != 2)) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    size = rtas_ld(args, 3);
+    addr = rtas_ld(args, 0);
+
+    finish_read_pci_config(spapr, buid, addr, size, rets);
+}
+
+static void rtas_read_pci_config(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    uint32_t size, addr;
+
+    if ((nargs != 2) || (nret != 2)) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    size = rtas_ld(args, 1);
+    addr = rtas_ld(args, 0);
+
+    finish_read_pci_config(spapr, 0, addr, size, rets);
+}
+
+static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+                                    uint32_t addr, uint32_t size,
+                                    uint32_t val, target_ulong rets)
+{
+    PCIDevice *pci_dev;
+
+    if ((size != 1) && (size != 2) && (size != 4)) {
+        /* access must be 1, 2 or 4 bytes */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    pci_dev = find_dev(spapr, buid, addr);
+    addr = rtas_pci_cfgaddr(addr);
+
+    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+        /* Access must be to a valid device, within bounds and
+         * naturally aligned */
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    pci_host_config_write_common(pci_dev, addr, pci_config_size(pci_dev),
+                                 val, size);
+
+    rtas_st(rets, 0, 0);
+}
+
+static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
+                                      uint32_t token, uint32_t nargs,
+                                      target_ulong args,
+                                      uint32_t nret, target_ulong rets)
+{
+    uint64_t buid;
+    uint32_t val, size, addr;
+
+    if ((nargs != 5) || (nret != 1)) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    val = rtas_ld(args, 4);
+    size = rtas_ld(args, 3);
+    addr = rtas_ld(args, 0);
+
+    finish_write_pci_config(spapr, buid, addr, size, val, rets);
+}
+
+static void rtas_write_pci_config(sPAPREnvironment *spapr,
+                                  uint32_t token, uint32_t nargs,
+                                  target_ulong args,
+                                  uint32_t nret, target_ulong rets)
+{
+    uint32_t val, size, addr;
+
+    if ((nargs != 3) || (nret != 1)) {
+        rtas_st(rets, 0, -1);
+        return;
+    }
+
+
+    val = rtas_ld(args, 2);
+    size = rtas_ld(args, 1);
+    addr = rtas_ld(args, 0);
+
+    finish_write_pci_config(spapr, 0, addr, size, val, rets);
+}
+
+/*
+ * Find an entry with config_addr or returns the empty one if not found AND
+ * alloc_new is set.
+ * At the moment the msi_table entries are never released so there is
+ * no point to look till the end of the list if we need to find the free entry.
+ */
+static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr,
+                             bool alloc_new)
+{
+    int i;
+
+    for (i = 0; i < SPAPR_MSIX_MAX_DEVS; ++i) {
+        if (!phb->msi_table[i].nvec) {
+            break;
+        }
+        if (phb->msi_table[i].config_addr == config_addr) {
+            return i;
+        }
+    }
+    if ((i < SPAPR_MSIX_MAX_DEVS) && alloc_new) {
+        trace_spapr_pci_msi("Allocating new MSI config", i, config_addr);
+        return i;
+    }
+
+    return -1;
+}
+
+/*
+ * Set MSI/MSIX message data.
+ * This is required for msi_notify()/msix_notify() which
+ * will write at the addresses via spapr_msi_write().
+ */
+static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr,
+                             bool msix, unsigned req_num)
+{
+    unsigned i;
+    MSIMessage msg = { .address = addr, .data = 0 };
+
+    if (!msix) {
+        msi_set_message(pdev, msg);
+        trace_spapr_pci_msi_setup(pdev->name, 0, msg.address);
+        return;
+    }
+
+    for (i = 0; i < req_num; ++i) {
+        msg.address = addr | (i << 2);
+        msix_set_message(pdev, i, msg);
+        trace_spapr_pci_msi_setup(pdev->name, i, msg.address);
+    }
+}
+
+static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
+                                uint32_t token, uint32_t nargs,
+                                target_ulong args, uint32_t nret,
+                                target_ulong rets)
+{
+    uint32_t config_addr = rtas_ld(args, 0);
+    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    unsigned int func = rtas_ld(args, 3);
+    unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */
+    unsigned int seq_num = rtas_ld(args, 5);
+    unsigned int ret_intr_type;
+    int ndev, irq;
+    sPAPRPHBState *phb = NULL;
+    PCIDevice *pdev = NULL;
+
+    switch (func) {
+    case RTAS_CHANGE_MSI_FN:
+    case RTAS_CHANGE_FN:
+        ret_intr_type = RTAS_TYPE_MSI;
+        break;
+    case RTAS_CHANGE_MSIX_FN:
+        ret_intr_type = RTAS_TYPE_MSIX;
+        break;
+    default:
+        fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);
+        rtas_st(rets, 0, -3); /* Parameter error */
+        return;
+    }
+
+    /* Fins sPAPRPHBState */
+    phb = find_phb(spapr, buid);
+    if (phb) {
+        pdev = find_dev(spapr, buid, config_addr);
+    }
+    if (!phb || !pdev) {
+        rtas_st(rets, 0, -3); /* Parameter error */
+        return;
+    }
+
+    /* Releasing MSIs */
+    if (!req_num) {
+        ndev = spapr_msicfg_find(phb, config_addr, false);
+        if (ndev < 0) {
+            trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
+            rtas_st(rets, 0, -1); /* Hardware error */
+            return;
+        }
+        trace_spapr_pci_msi("Released MSIs", ndev, config_addr);
+        rtas_st(rets, 0, 0);
+        rtas_st(rets, 1, 0);
+        return;
+    }
+
+    /* Enabling MSI */
+
+    /* Find a device number in the map to add or reuse the existing one */
+    ndev = spapr_msicfg_find(phb, config_addr, true);
+    if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {
+        fprintf(stderr, "No free entry for a new MSI device\n");
+        rtas_st(rets, 0, -1); /* Hardware error */
+        return;
+    }
+    trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);
+
+    /* Check if there is an old config and MSI number has not changed */
+    if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
+        /* Unexpected behaviour */
+        fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);
+        rtas_st(rets, 0, -1); /* Hardware error */
+        return;
+    }
+
+    /* There is no cached config, allocate MSIs */
+    if (!phb->msi_table[ndev].nvec) {
+        irq = spapr_allocate_irq_block(req_num, false);
+        if (irq < 0) {
+            fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
+            rtas_st(rets, 0, -1); /* Hardware error */
+            return;
+        }
+        phb->msi_table[ndev].irq = irq;
+        phb->msi_table[ndev].nvec = req_num;
+        phb->msi_table[ndev].config_addr = config_addr;
+    }
+
+    /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */
+    spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16),
+                     ret_intr_type == RTAS_TYPE_MSIX, req_num);
+
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, req_num);
+    rtas_st(rets, 2, ++seq_num);
+    rtas_st(rets, 3, ret_intr_type);
+
+    trace_spapr_pci_rtas_ibm_change_msi(func, req_num);
+}
+
+static void rtas_ibm_query_interrupt_source_number(sPAPREnvironment *spapr,
+                                                   uint32_t token,
+                                                   uint32_t nargs,
+                                                   target_ulong args,
+                                                   uint32_t nret,
+                                                   target_ulong rets)
+{
+    uint32_t config_addr = rtas_ld(args, 0);
+    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
+    unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
+    int ndev;
+    sPAPRPHBState *phb = NULL;
+
+    /* Fins sPAPRPHBState */
+    phb = find_phb(spapr, buid);
+    if (!phb) {
+        rtas_st(rets, 0, -3); /* Parameter error */
+        return;
+    }
+
+    /* Find device descriptor and start IRQ */
+    ndev = spapr_msicfg_find(phb, config_addr, false);
+    if (ndev < 0) {
+        trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
+        rtas_st(rets, 0, -1); /* Hardware error */
+        return;
+    }
+
+    intr_src_num = phb->msi_table[ndev].irq + ioa_intr_num;
+    trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num,
+                                                           intr_src_num);
+
+    rtas_st(rets, 0, 0);
+    rtas_st(rets, 1, intr_src_num);
+    rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */
+}
+
+static int pci_spapr_swizzle(int slot, int pin)
+{
+    return (slot + pin) % PCI_NUM_PINS;
+}
+
+static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    /*
+     * Here we need to convert pci_dev + irq_num to some unique value
+     * which is less than number of IRQs on the specific bus (4).  We
+     * use standard PCI swizzling, that is (slot number + pin number)
+     * % 4.
+     */
+    return pci_spapr_swizzle(PCI_SLOT(pci_dev->devfn), irq_num);
+}
+
+static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
+{
+    /*
+     * Here we use the number returned by pci_spapr_map_irq to find a
+     * corresponding qemu_irq.
+     */
+    sPAPRPHBState *phb = opaque;
+
+    trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq);
+    qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
+}
+
+static uint64_t spapr_io_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    switch (size) {
+    case 1:
+        return cpu_inb(addr);
+    case 2:
+        return cpu_inw(addr);
+    case 4:
+        return cpu_inl(addr);
+    }
+    assert(0);
+}
+
+static void spapr_io_write(void *opaque, hwaddr addr,
+                           uint64_t data, unsigned size)
+{
+    switch (size) {
+    case 1:
+        cpu_outb(addr, data);
+        return;
+    case 2:
+        cpu_outw(addr, data);
+        return;
+    case 4:
+        cpu_outl(addr, data);
+        return;
+    }
+    assert(0);
+}
+
+static const MemoryRegionOps spapr_io_ops = {
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .read = spapr_io_read,
+    .write = spapr_io_write
+};
+
+/*
+ * MSI/MSIX memory region implementation.
+ * The handler handles both MSI and MSIX.
+ * For MSI-X, the vector number is encoded as a part of the address,
+ * data is set to 0.
+ * For MSI, the vector number is encoded in least bits in data.
+ */
+static void spapr_msi_write(void *opaque, hwaddr addr,
+                            uint64_t data, unsigned size)
+{
+    sPAPRPHBState *phb = opaque;
+    int ndev = addr >> 16;
+    int vec = ((addr & 0xFFFF) >> 2) | data;
+    uint32_t irq = phb->msi_table[ndev].irq + vec;
+
+    trace_spapr_pci_msi_write(addr, data, irq);
+
+    qemu_irq_pulse(xics_get_qirq(spapr->icp, irq));
+}
+
+static const MemoryRegionOps spapr_msi_ops = {
+    /* There is no .read as the read result is undefined by PCI spec */
+    .read = NULL,
+    .write = spapr_msi_write,
+    .endianness = DEVICE_LITTLE_ENDIAN
+};
+
+/*
+ * PHB PCI device
+ */
+static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
+                                            int devfn)
+{
+    sPAPRPHBState *phb = opaque;
+
+    return phb->dma;
+}
+
+static int spapr_phb_init(SysBusDevice *s)
+{
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    const char *busname;
+    char *namebuf;
+    int i;
+    PCIBus *bus;
+
+    if (sphb->index != -1) {
+        hwaddr windows_base;
+
+        if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
+            || (sphb->mem_win_addr != -1)
+            || (sphb->io_win_addr != -1)
+            || (sphb->msi_win_addr != -1)) {
+            fprintf(stderr, "Either \"index\" or other parameters must"
+                    " be specified for PAPR PHB, not both\n");
+            return -1;
+        }
+
+        sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
+        sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index;
+
+        windows_base = SPAPR_PCI_WINDOW_BASE
+            + sphb->index * SPAPR_PCI_WINDOW_SPACING;
+        sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF;
+        sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF;
+        sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF;
+    }
+
+    if (sphb->buid == -1) {
+        fprintf(stderr, "BUID not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->dma_liobn == -1) {
+        fprintf(stderr, "LIOBN not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->mem_win_addr == -1) {
+        fprintf(stderr, "Memory window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->io_win_addr == -1) {
+        fprintf(stderr, "IO window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->msi_win_addr == -1) {
+        fprintf(stderr, "MSI window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (find_phb(spapr, sphb->buid)) {
+        fprintf(stderr, "PCI host bridges must have unique BUIDs\n");
+        return -1;
+    }
+
+    sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
+
+    namebuf = alloca(strlen(sphb->dtbusname) + 32);
+
+    /* Initialize memory regions */
+    sprintf(namebuf, "%s.mmio", sphb->dtbusname);
+    memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
+
+    sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
+    memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
+                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
+    memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
+                                &sphb->memwindow);
+
+    /* On ppc, we only have MMIO no specific IO space from the CPU
+     * perspective.  In theory we ought to be able to embed the PCI IO
+     * memory region direction in the system memory space.  However,
+     * if any of the IO BAR subregions use the old_portio mechanism,
+     * that won't be processed properly unless accessed from the
+     * system io address space.  This hack to bounce things via
+     * system_io works around the problem until all the users of
+     * old_portion are updated */
+    sprintf(namebuf, "%s.io", sphb->dtbusname);
+    memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    /* FIXME: fix to support multiple PHBs */
+    memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
+
+    sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
+    memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
+                          namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
+                                &sphb->iowindow);
+
+    /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
+     * we need to allocate some memory to catch those writes coming
+     * from msi_notify()/msix_notify() */
+    if (msi_supported) {
+        sprintf(namebuf, "%s.msi", sphb->dtbusname);
+        memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
+                              namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
+        memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
+                                    &sphb->msiwindow);
+    }
+
+    /*
+     * Selecting a busname is more complex than you'd think, due to
+     * interacting constraints.  If the user has specified an id
+     * explicitly for the phb , then we want to use the qdev default
+     * of naming the bus based on the bridge device (so the user can
+     * then assign devices to it in the way they expect).  For the
+     * first / default PCI bus (index=0) we want to use just "pci"
+     * because libvirt expects there to be a bus called, simply,
+     * "pci".  Otherwise, we use the same name as in the device tree,
+     * since it's unique by construction, and makes the guest visible
+     * BUID clear.
+     */
+    if (s->qdev.id) {
+        busname = NULL;
+    } else if (sphb->index == 0) {
+        busname = "pci";
+    } else {
+        busname = sphb->dtbusname;
+    }
+    bus = pci_register_bus(DEVICE(s), busname,
+                           pci_spapr_set_irq, pci_spapr_map_irq, sphb,
+                           &sphb->memspace, &sphb->iospace,
+                           PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
+    phb->bus = bus;
+
+    sphb->dma_window_start = 0;
+    sphb->dma_window_size = 0x40000000;
+    sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
+    if (!sphb->dma) {
+        fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
+        return -1;
+    }
+    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
+
+    QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
+
+    /* Initialize the LSI table */
+    for (i = 0; i < PCI_NUM_PINS; i++) {
+        uint32_t irq;
+
+        irq = spapr_allocate_lsi(0);
+        if (!irq) {
+            return -1;
+        }
+
+        sphb->lsi_table[i].irq = irq;
+    }
+
+    return 0;
+}
+
+static void spapr_phb_reset(DeviceState *qdev)
+{
+    SysBusDevice *s = SYS_BUS_DEVICE(qdev);
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+
+    /* Reset the IOMMU state */
+    spapr_tce_reset(sphb->dma);
+}
+
+static Property spapr_phb_properties[] = {
+    DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
+    DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
+    DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
+    DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
+    DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size,
+                      SPAPR_PCI_MMIO_WIN_SIZE),
+    DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
+    DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size,
+                      SPAPR_PCI_IO_WIN_SIZE),
+    DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_phb_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    sdc->init = spapr_phb_init;
+    dc->props = spapr_phb_properties;
+    dc->reset = spapr_phb_reset;
+}
+
+static const TypeInfo spapr_phb_info = {
+    .name          = TYPE_SPAPR_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
+    .instance_size = sizeof(sPAPRPHBState),
+    .class_init    = spapr_phb_class_init,
+};
+
+PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
+    qdev_prop_set_uint32(dev, "index", index);
+    qdev_init_nofail(dev);
+
+    return PCI_HOST_BRIDGE(dev);
+}
+
+/* Macros to operate with address in OF binding to PCI */
+#define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
+#define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
+#define b_p(x)          b_x((x), 30, 1) /* 1 if prefetchable */
+#define b_t(x)          b_x((x), 29, 1) /* 1 if the address is aliased */
+#define b_ss(x)         b_x((x), 24, 2) /* the space code */
+#define b_bbbbbbbb(x)   b_x((x), 16, 8) /* bus number */
+#define b_ddddd(x)      b_x((x), 11, 5) /* device number */
+#define b_fff(x)        b_x((x), 8, 3)  /* function number */
+#define b_rrrrrrrr(x)   b_x((x), 0, 8)  /* register number */
+
+int spapr_populate_pci_dt(sPAPRPHBState *phb,
+                          uint32_t xics_phandle,
+                          void *fdt)
+{
+    int bus_off, i, j;
+    char nodename[256];
+    uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
+    struct {
+        uint32_t hi;
+        uint64_t child;
+        uint64_t parent;
+        uint64_t size;
+    } QEMU_PACKED ranges[] = {
+        {
+            cpu_to_be32(b_ss(1)), cpu_to_be64(0),
+            cpu_to_be64(phb->io_win_addr),
+            cpu_to_be64(memory_region_size(&phb->iospace)),
+        },
+        {
+            cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
+            cpu_to_be64(phb->mem_win_addr),
+            cpu_to_be64(memory_region_size(&phb->memwindow)),
+        },
+    };
+    uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
+    uint32_t interrupt_map_mask[] = {
+        cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
+    uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
+
+    /* Start populating the FDT */
+    sprintf(nodename, "pci@%" PRIx64, phb->buid);
+    bus_off = fdt_add_subnode(fdt, 0, nodename);
+    if (bus_off < 0) {
+        return bus_off;
+    }
+
+#define _FDT(exp) \
+    do { \
+        int ret = (exp);                                           \
+        if (ret < 0) {                                             \
+            return ret;                                            \
+        }                                                          \
+    } while (0)
+
+    /* Write PHB properties */
+    _FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
+    _FDT(fdt_setprop_string(fdt, bus_off, "compatible", "IBM,Logical_PHB"));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#address-cells", 0x3));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#size-cells", 0x2));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
+    _FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
+    _FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
+    _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
+    _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
+    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
+
+    /* Build the interrupt-map, this must matches what is done
+     * in pci_spapr_map_irq
+     */
+    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
+                     &interrupt_map_mask, sizeof(interrupt_map_mask)));
+    for (i = 0; i < PCI_SLOT_MAX; i++) {
+        for (j = 0; j < PCI_NUM_PINS; j++) {
+            uint32_t *irqmap = interrupt_map[i*PCI_NUM_PINS + j];
+            int lsi_num = pci_spapr_swizzle(i, j);
+
+            irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
+            irqmap[1] = 0;
+            irqmap[2] = 0;
+            irqmap[3] = cpu_to_be32(j+1);
+            irqmap[4] = cpu_to_be32(xics_phandle);
+            irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq);
+            irqmap[6] = cpu_to_be32(0x8);
+        }
+    }
+    /* Write interrupt map */
+    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
+                     sizeof(interrupt_map)));
+
+    spapr_dma_dt(fdt, bus_off, "ibm,dma-window",
+                 phb->dma_liobn, phb->dma_window_start,
+                 phb->dma_window_size);
+
+    return 0;
+}
+
+void spapr_pci_rtas_init(void)
+{
+    spapr_rtas_register("read-pci-config", rtas_read_pci_config);
+    spapr_rtas_register("write-pci-config", rtas_write_pci_config);
+    spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
+    spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
+    if (msi_supported) {
+        spapr_rtas_register("ibm,query-interrupt-source-number",
+                            rtas_ibm_query_interrupt_source_number);
+        spapr_rtas_register("ibm,change-msi", rtas_ibm_change_msi);
+    }
+}
+
+static void spapr_pci_register_types(void)
+{
+    type_register_static(&spapr_phb_info);
+}
+
+type_init(spapr_pci_register_types)
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
deleted file mode 100644 (file)
index 599539b..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * 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/>.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-/* This file implements emulation of the 32-bit PCI controller found in some
- * 4xx SoCs, such as the 440EP. */
-
-#include "hw/hw.h"
-#include "hw/ppc/ppc.h"
-#include "hw/ppc/ppc4xx.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "exec/address-spaces.h"
-
-#undef DEBUG
-#ifdef DEBUG
-#define DPRINTF(fmt, ...) do { printf(fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...)
-#endif /* DEBUG */
-
-struct PCIMasterMap {
-    uint32_t la;
-    uint32_t ma;
-    uint32_t pcila;
-    uint32_t pciha;
-};
-
-struct PCITargetMap {
-    uint32_t ms;
-    uint32_t la;
-};
-
-#define PPC4xx_PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PPC4xxPCIState, (obj), TYPE_PPC4xx_PCI_HOST_BRIDGE)
-
-#define PPC4xx_PCI_NR_PMMS 3
-#define PPC4xx_PCI_NR_PTMS 2
-
-struct PPC4xxPCIState {
-    PCIHostState parent_obj;
-
-    struct PCIMasterMap pmm[PPC4xx_PCI_NR_PMMS];
-    struct PCITargetMap ptm[PPC4xx_PCI_NR_PTMS];
-    qemu_irq irq[4];
-
-    MemoryRegion container;
-    MemoryRegion iomem;
-};
-typedef struct PPC4xxPCIState PPC4xxPCIState;
-
-#define PCIC0_CFGADDR       0x0
-#define PCIC0_CFGDATA       0x4
-
-/* PLB Memory Map (PMM) registers specify which PLB addresses are translated to
- * PCI accesses. */
-#define PCIL0_PMM0LA        0x0
-#define PCIL0_PMM0MA        0x4
-#define PCIL0_PMM0PCILA     0x8
-#define PCIL0_PMM0PCIHA     0xc
-#define PCIL0_PMM1LA        0x10
-#define PCIL0_PMM1MA        0x14
-#define PCIL0_PMM1PCILA     0x18
-#define PCIL0_PMM1PCIHA     0x1c
-#define PCIL0_PMM2LA        0x20
-#define PCIL0_PMM2MA        0x24
-#define PCIL0_PMM2PCILA     0x28
-#define PCIL0_PMM2PCIHA     0x2c
-
-/* PCI Target Map (PTM) registers specify which PCI addresses are translated to
- * PLB accesses. */
-#define PCIL0_PTM1MS        0x30
-#define PCIL0_PTM1LA        0x34
-#define PCIL0_PTM2MS        0x38
-#define PCIL0_PTM2LA        0x3c
-#define PCI_REG_BASE        0x800000
-#define PCI_REG_SIZE        0x40
-
-#define PCI_ALL_SIZE        (PCI_REG_BASE + PCI_REG_SIZE)
-
-static uint64_t pci4xx_cfgaddr_read(void *opaque, hwaddr addr,
-                                    unsigned size)
-{
-    PPC4xxPCIState *ppc4xx_pci = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
-
-    return phb->config_reg;
-}
-
-static void pci4xx_cfgaddr_write(void *opaque, hwaddr addr,
-                                  uint64_t value, unsigned size)
-{
-    PPC4xxPCIState *ppc4xx_pci = opaque;
-    PCIHostState *phb = PCI_HOST_BRIDGE(ppc4xx_pci);
-
-    phb->config_reg = value & ~0x3;
-}
-
-static const MemoryRegionOps pci4xx_cfgaddr_ops = {
-    .read = pci4xx_cfgaddr_read,
-    .write = pci4xx_cfgaddr_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset,
-                                  uint64_t value, unsigned size)
-{
-    struct PPC4xxPCIState *pci = opaque;
-
-    /* We ignore all target attempts at PCI configuration, effectively
-     * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
-
-    switch (offset) {
-    case PCIL0_PMM0LA:
-        pci->pmm[0].la = value;
-        break;
-    case PCIL0_PMM0MA:
-        pci->pmm[0].ma = value;
-        break;
-    case PCIL0_PMM0PCIHA:
-        pci->pmm[0].pciha = value;
-        break;
-    case PCIL0_PMM0PCILA:
-        pci->pmm[0].pcila = value;
-        break;
-
-    case PCIL0_PMM1LA:
-        pci->pmm[1].la = value;
-        break;
-    case PCIL0_PMM1MA:
-        pci->pmm[1].ma = value;
-        break;
-    case PCIL0_PMM1PCIHA:
-        pci->pmm[1].pciha = value;
-        break;
-    case PCIL0_PMM1PCILA:
-        pci->pmm[1].pcila = value;
-        break;
-
-    case PCIL0_PMM2LA:
-        pci->pmm[2].la = value;
-        break;
-    case PCIL0_PMM2MA:
-        pci->pmm[2].ma = value;
-        break;
-    case PCIL0_PMM2PCIHA:
-        pci->pmm[2].pciha = value;
-        break;
-    case PCIL0_PMM2PCILA:
-        pci->pmm[2].pcila = value;
-        break;
-
-    case PCIL0_PTM1MS:
-        pci->ptm[0].ms = value;
-        break;
-    case PCIL0_PTM1LA:
-        pci->ptm[0].la = value;
-        break;
-    case PCIL0_PTM2MS:
-        pci->ptm[1].ms = value;
-        break;
-    case PCIL0_PTM2LA:
-        pci->ptm[1].la = value;
-        break;
-
-    default:
-        printf("%s: unhandled PCI internal register 0x%lx\n", __func__,
-               (unsigned long)offset);
-        break;
-    }
-}
-
-static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset,
-                                     unsigned size)
-{
-    struct PPC4xxPCIState *pci = opaque;
-    uint32_t value;
-
-    switch (offset) {
-    case PCIL0_PMM0LA:
-        value = pci->pmm[0].la;
-        break;
-    case PCIL0_PMM0MA:
-        value = pci->pmm[0].ma;
-        break;
-    case PCIL0_PMM0PCIHA:
-        value = pci->pmm[0].pciha;
-        break;
-    case PCIL0_PMM0PCILA:
-        value = pci->pmm[0].pcila;
-        break;
-
-    case PCIL0_PMM1LA:
-        value = pci->pmm[1].la;
-        break;
-    case PCIL0_PMM1MA:
-        value = pci->pmm[1].ma;
-        break;
-    case PCIL0_PMM1PCIHA:
-        value = pci->pmm[1].pciha;
-        break;
-    case PCIL0_PMM1PCILA:
-        value = pci->pmm[1].pcila;
-        break;
-
-    case PCIL0_PMM2LA:
-        value = pci->pmm[2].la;
-        break;
-    case PCIL0_PMM2MA:
-        value = pci->pmm[2].ma;
-        break;
-    case PCIL0_PMM2PCIHA:
-        value = pci->pmm[2].pciha;
-        break;
-    case PCIL0_PMM2PCILA:
-        value = pci->pmm[2].pcila;
-        break;
-
-    case PCIL0_PTM1MS:
-        value = pci->ptm[0].ms;
-        break;
-    case PCIL0_PTM1LA:
-        value = pci->ptm[0].la;
-        break;
-    case PCIL0_PTM2MS:
-        value = pci->ptm[1].ms;
-        break;
-    case PCIL0_PTM2LA:
-        value = pci->ptm[1].la;
-        break;
-
-    default:
-        printf("%s: invalid PCI internal register 0x%lx\n", __func__,
-               (unsigned long)offset);
-        value = 0;
-    }
-
-    return value;
-}
-
-static const MemoryRegionOps pci_reg_ops = {
-    .read = ppc4xx_pci_reg_read4,
-    .write = ppc4xx_pci_reg_write4,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void ppc4xx_pci_reset(void *opaque)
-{
-    struct PPC4xxPCIState *pci = opaque;
-
-    memset(pci->pmm, 0, sizeof(pci->pmm));
-    memset(pci->ptm, 0, sizeof(pci->ptm));
-}
-
-/* On Bamboo, all pins from each slot are tied to a single board IRQ. This
- * may need further refactoring for other boards. */
-static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    int slot = pci_dev->devfn >> 3;
-
-    DPRINTF("%s: devfn %x irq %d -> %d\n", __func__,
-            pci_dev->devfn, irq_num, slot);
-
-    return slot - 1;
-}
-
-static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pci_irqs = opaque;
-
-    DPRINTF("%s: PCI irq %d\n", __func__, irq_num);
-    if (irq_num < 0) {
-        fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num);
-        return;
-    }
-    qemu_set_irq(pci_irqs[irq_num], level);
-}
-
-static const VMStateDescription vmstate_pci_master_map = {
-    .name = "pci_master_map",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(la, struct PCIMasterMap),
-        VMSTATE_UINT32(ma, struct PCIMasterMap),
-        VMSTATE_UINT32(pcila, struct PCIMasterMap),
-        VMSTATE_UINT32(pciha, struct PCIMasterMap),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_pci_target_map = {
-    .name = "pci_target_map",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32(ms, struct PCITargetMap),
-        VMSTATE_UINT32(la, struct PCITargetMap),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_ppc4xx_pci = {
-    .name = "ppc4xx_pci",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
-                             vmstate_pci_master_map,
-                             struct PCIMasterMap),
-        VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
-                             vmstate_pci_target_map,
-                             struct PCITargetMap),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-/* XXX Interrupt acknowledge cycles not supported. */
-static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
-{
-    PPC4xxPCIState *s;
-    PCIHostState *h;
-    PCIBus *b;
-    int i;
-
-    h = PCI_HOST_BRIDGE(dev);
-    s = PPC4xx_PCI_HOST_BRIDGE(dev);
-
-    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
-    }
-
-    b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
-                         ppc4xx_pci_map_irq, s->irq, get_system_memory(),
-                         get_system_io(), 0, 4, TYPE_PCI_BUS);
-    h->bus = b;
-
-    pci_create_simple(b, 0, "ppc4xx-host-bridge");
-
-    /* XXX split into 2 memory regions, one for config space, one for regs */
-    memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE);
-    memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h,
-                          "pci-conf-idx", 4);
-    memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
-                          "pci-conf-data", 4);
-    memory_region_init_io(&s->iomem, &pci_reg_ops, s,
-                          "pci.reg", PCI_REG_SIZE);
-    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
-    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
-    memory_region_add_subregion(&s->container, PCI_REG_BASE, &s->iomem);
-    sysbus_init_mmio(dev, &s->container);
-    qemu_register_reset(ppc4xx_pci_reset, s);
-
-    return 0;
-}
-
-static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->desc        = "Host bridge";
-    k->vendor_id    = PCI_VENDOR_ID_IBM;
-    k->device_id    = PCI_DEVICE_ID_IBM_440GX;
-    k->class_id     = PCI_CLASS_BRIDGE_OTHER;
-}
-
-static const TypeInfo ppc4xx_host_bridge_info = {
-    .name          = "ppc4xx-host-bridge",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = ppc4xx_host_bridge_class_init,
-};
-
-static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    k->init = ppc4xx_pcihost_initfn;
-    dc->vmsd = &vmstate_ppc4xx_pci;
-}
-
-static const TypeInfo ppc4xx_pcihost_info = {
-    .name          = TYPE_PPC4xx_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(PPC4xxPCIState),
-    .class_init    = ppc4xx_pcihost_class_init,
-};
-
-static void ppc4xx_pci_register_types(void)
-{
-    type_register_static(&ppc4xx_pcihost_info);
-    type_register_static(&ppc4xx_host_bridge_info);
-}
-
-type_init(ppc4xx_pci_register_types)
diff --git a/hw/q35.c b/hw/q35.c
deleted file mode 100644 (file)
index 8467f86..0000000
--- a/hw/q35.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * QEMU MCH/ICH9 PCI Bridge Emulation
- *
- * Copyright (c) 2006 Fabrice Bellard
- * Copyright (c) 2009, 2010, 2011
- *               Isaku Yamahata <yamahata at valinux co jp>
- *               VA Linux Systems Japan K.K.
- * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
- *
- * This is based on piix_pci.c, but heavily modified.
- *
- * 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/hw.h"
-#include "hw/pci-host/q35.h"
-
-/****************************************************************************
- * Q35 host
- */
-
-static int q35_host_init(SysBusDevice *dev)
-{
-    PCIBus *b;
-    PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev);
-    Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev);
-
-    memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci,
-                          "pci-conf-idx", 4);
-    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
-    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
-
-    memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci,
-                          "pci-conf-data", 4);
-    sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
-    sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
-
-    if (pcie_host_init(&s->host) < 0) {
-        return -1;
-    }
-    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
-                    s->mch.pci_address_space, s->mch.address_space_io,
-                    0, TYPE_PCIE_BUS);
-    s->host.pci.bus = b;
-    qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
-    qdev_init_nofail(DEVICE(&s->mch));
-
-    return 0;
-}
-
-static Property mch_props[] = {
-    DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr,
-                        MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void q35_host_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = q35_host_init;
-    dc->props = mch_props;
-}
-
-static void q35_host_initfn(Object *obj)
-{
-    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
-
-    object_initialize(&s->mch, TYPE_MCH_PCI_DEVICE);
-    object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
-    qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
-    qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
-}
-
-static const TypeInfo q35_host_info = {
-    .name       = TYPE_Q35_HOST_DEVICE,
-    .parent     = TYPE_PCIE_HOST_BRIDGE,
-    .instance_size = sizeof(Q35PCIHost),
-    .instance_init = q35_host_initfn,
-    .class_init = q35_host_class_init,
-};
-
-/****************************************************************************
- * MCH D0:F0
- */
-
-/* PCIe MMCFG */
-static void mch_update_pciexbar(MCHPCIState *mch)
-{
-    PCIDevice *pci_dev = &mch->d;
-    BusState *bus = qdev_get_parent_bus(&pci_dev->qdev);
-    DeviceState *qdev = bus->parent;
-    Q35PCIHost *s = Q35_HOST_DEVICE(qdev);
-
-    uint64_t pciexbar;
-    int enable;
-    uint64_t addr;
-    uint64_t addr_mask;
-    uint32_t length;
-
-    pciexbar = pci_get_quad(pci_dev->config + MCH_HOST_BRIDGE_PCIEXBAR);
-    enable = pciexbar & MCH_HOST_BRIDGE_PCIEXBAREN;
-    addr_mask = MCH_HOST_BRIDGE_PCIEXBAR_ADMSK;
-    switch (pciexbar & MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK) {
-    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M:
-        length = 256 * 1024 * 1024;
-        break;
-    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M:
-        length = 128 * 1024 * 1024;
-        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK |
-            MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
-        break;
-    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M:
-        length = 64 * 1024 * 1024;
-        addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
-        break;
-    case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
-    default:
-        enable = 0;
-        length = 0;
-        abort();
-        break;
-    }
-    addr = pciexbar & addr_mask;
-    pcie_host_mmcfg_update(&s->host, enable, addr, length);
-}
-
-/* PAM */
-static void mch_update_pam(MCHPCIState *mch)
-{
-    int i;
-
-    memory_region_transaction_begin();
-    for (i = 0; i < 13; i++) {
-        pam_update(&mch->pam_regions[i], i,
-                   mch->d.config[MCH_HOST_BRIDGE_PAM0 + ((i + 1) / 2)]);
-    }
-    memory_region_transaction_commit();
-}
-
-/* SMRAM */
-static void mch_update_smram(MCHPCIState *mch)
-{
-    memory_region_transaction_begin();
-    smram_update(&mch->smram_region, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
-                    mch->smm_enabled);
-    memory_region_transaction_commit();
-}
-
-static void mch_set_smm(int smm, void *arg)
-{
-    MCHPCIState *mch = arg;
-
-    memory_region_transaction_begin();
-    smram_set_smm(&mch->smm_enabled, smm, mch->d.config[MCH_HOST_BRDIGE_SMRAM],
-                    &mch->smram_region);
-    memory_region_transaction_commit();
-}
-
-static void mch_write_config(PCIDevice *d,
-                              uint32_t address, uint32_t val, int len)
-{
-    MCHPCIState *mch = MCH_PCI_DEVICE(d);
-
-    /* XXX: implement SMRAM.D_LOCK */
-    pci_default_write_config(d, address, val, len);
-
-    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0,
-                       MCH_HOST_BRIDGE_PAM_SIZE)) {
-        mch_update_pam(mch);
-    }
-
-    if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR,
-                       MCH_HOST_BRIDGE_PCIEXBAR_SIZE)) {
-        mch_update_pciexbar(mch);
-    }
-
-    if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM,
-                       MCH_HOST_BRDIGE_SMRAM_SIZE)) {
-        mch_update_smram(mch);
-    }
-}
-
-static void mch_update(MCHPCIState *mch)
-{
-    mch_update_pciexbar(mch);
-    mch_update_pam(mch);
-    mch_update_smram(mch);
-}
-
-static int mch_post_load(void *opaque, int version_id)
-{
-    MCHPCIState *mch = opaque;
-    mch_update(mch);
-    return 0;
-}
-
-static const VMStateDescription vmstate_mch = {
-    .name = "mch",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = mch_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(d, MCHPCIState),
-        VMSTATE_UINT8(smm_enabled, MCHPCIState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mch_reset(DeviceState *qdev)
-{
-    PCIDevice *d = PCI_DEVICE(qdev);
-    MCHPCIState *mch = MCH_PCI_DEVICE(d);
-
-    pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR,
-                 MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
-
-    d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
-
-    mch_update(mch);
-}
-
-static int mch_init(PCIDevice *d)
-{
-    int i;
-    hwaddr pci_hole64_size;
-    MCHPCIState *mch = MCH_PCI_DEVICE(d);
-
-    /* setup pci memory regions */
-    memory_region_init_alias(&mch->pci_hole, "pci-hole",
-                             mch->pci_address_space,
-                             mch->below_4g_mem_size,
-                             0x100000000ULL - mch->below_4g_mem_size);
-    memory_region_add_subregion(mch->system_memory, mch->below_4g_mem_size,
-                                &mch->pci_hole);
-    pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
-                       ((uint64_t)1 << 62));
-    memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64",
-                             mch->pci_address_space,
-                             0x100000000ULL + mch->above_4g_mem_size,
-                             pci_hole64_size);
-    if (pci_hole64_size) {
-        memory_region_add_subregion(mch->system_memory,
-                                    0x100000000ULL + mch->above_4g_mem_size,
-                                    &mch->pci_hole_64bit);
-    }
-    /* smram */
-    cpu_smm_register(&mch_set_smm, mch);
-    memory_region_init_alias(&mch->smram_region, "smram-region",
-                             mch->pci_address_space, 0xa0000, 0x20000);
-    memory_region_add_subregion_overlap(mch->system_memory, 0xa0000,
-                                        &mch->smram_region, 1);
-    memory_region_set_enabled(&mch->smram_region, false);
-    init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
-             &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
-    for (i = 0; i < 12; ++i) {
-        init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space,
-                 &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
-                 PAM_EXPAN_SIZE);
-    }
-    return 0;
-}
-
-static void mch_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    k->init = mch_init;
-    k->config_write = mch_write_config;
-    dc->reset = mch_reset;
-    dc->desc = "Host bridge";
-    dc->vmsd = &vmstate_mch;
-    k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH;
-    k->revision = MCH_HOST_BRIDGE_REVISION_DEFUALT;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-}
-
-static const TypeInfo mch_info = {
-    .name = TYPE_MCH_PCI_DEVICE,
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(MCHPCIState),
-    .class_init = mch_class_init,
-};
-
-static void q35_register(void)
-{
-    type_register_static(&mch_info);
-    type_register_static(&q35_host_info);
-}
-
-type_init(q35_register);
index 76b37bbf6bd95eb25e2712ae6cdbdb9e72277cd4..0387b96b4bef9d1d1781d61477d41a968453ecf1 100644 (file)
@@ -1,7 +1,8 @@
-obj-y += sh_intc.o sh_pci.o
+obj-y += sh_intc.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
 obj-y += shix.o r2d.o
 
 obj-y += sh7750.o sh7750_regnames.o
+obj-y += sh_pci.o
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
new file mode 100644 (file)
index 0000000..d213a90
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * SuperH on-chip PCIC emulation.
+ *
+ * Copyright (c) 2008 Takashi YOSHII
+ *
+ * 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/sysbus.h"
+#include "hw/sh4/sh.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "qemu/bswap.h"
+#include "exec/address-spaces.h"
+
+typedef struct SHPCIState {
+    SysBusDevice busdev;
+    PCIBus *bus;
+    PCIDevice *dev;
+    qemu_irq irq[4];
+    MemoryRegion memconfig_p4;
+    MemoryRegion memconfig_a7;
+    MemoryRegion isa;
+    uint32_t par;
+    uint32_t mbr;
+    uint32_t iobr;
+} SHPCIState;
+
+static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
+                              unsigned size)
+{
+    SHPCIState *pcic = p;
+    switch(addr) {
+    case 0 ... 0xfc:
+        cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
+        break;
+    case 0x1c0:
+        pcic->par = val;
+        break;
+    case 0x1c4:
+        pcic->mbr = val & 0xff000001;
+        break;
+    case 0x1c8:
+        if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
+            memory_region_del_subregion(get_system_memory(), &pcic->isa);
+            pcic->iobr = val & 0xfffc0001;
+            memory_region_add_subregion(get_system_memory(),
+                                        pcic->iobr & 0xfffc0000, &pcic->isa);
+        }
+        break;
+    case 0x220:
+        pci_data_write(pcic->bus, pcic->par, val, 4);
+        break;
+    }
+}
+
+static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
+                                 unsigned size)
+{
+    SHPCIState *pcic = p;
+    switch(addr) {
+    case 0 ... 0xfc:
+        return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
+    case 0x1c0:
+        return pcic->par;
+    case 0x1c4:
+        return pcic->mbr;
+    case 0x1c8:
+        return pcic->iobr;
+    case 0x220:
+        return pci_data_read(pcic->bus, pcic->par, 4);
+    }
+    return 0;
+}
+
+static const MemoryRegionOps sh_pci_reg_ops = {
+    .read = sh_pci_reg_read,
+    .write = sh_pci_reg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static int sh_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    return (d->devfn >> 3);
+}
+
+static void sh_pci_set_irq(void *opaque, int irq_num, int level)
+{
+    qemu_irq *pic = opaque;
+
+    qemu_set_irq(pic[irq_num], level);
+}
+
+static int sh_pci_device_init(SysBusDevice *dev)
+{
+    SHPCIState *s;
+    int i;
+
+    s = FROM_SYSBUS(SHPCIState, dev);
+    for (i = 0; i < 4; i++) {
+        sysbus_init_irq(dev, &s->irq[i]);
+    }
+    s->bus = pci_register_bus(&s->busdev.qdev, "pci",
+                              sh_pci_set_irq, sh_pci_map_irq,
+                              s->irq,
+                              get_system_memory(),
+                              get_system_io(),
+                              PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
+    memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s,
+                          "sh_pci", 0x224);
+    memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
+                             0, 0x224);
+    isa_mmio_setup(&s->isa, 0x40000);
+    sysbus_init_mmio(dev, &s->memconfig_p4);
+    sysbus_init_mmio(dev, &s->memconfig_a7);
+    s->iobr = 0xfe240000;
+    memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
+
+    s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
+    return 0;
+}
+
+static int sh_pci_host_init(PCIDevice *d)
+{
+    pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
+    pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
+                 PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+    return 0;
+}
+
+static void sh_pci_host_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = sh_pci_host_init;
+    k->vendor_id = PCI_VENDOR_ID_HITACHI;
+    k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
+}
+
+static const TypeInfo sh_pci_host_info = {
+    .name          = "sh_pci_host",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .class_init    = sh_pci_host_class_init,
+};
+
+static void sh_pci_device_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = sh_pci_device_init;
+}
+
+static const TypeInfo sh_pci_device_info = {
+    .name          = "sh_pci",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SHPCIState),
+    .class_init    = sh_pci_device_class_init,
+};
+
+static void sh_pci_register_types(void)
+{
+    type_register_static(&sh_pci_device_info);
+    type_register_static(&sh_pci_host_info);
+}
+
+type_init(sh_pci_register_types)
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
deleted file mode 100644 (file)
index d213a90..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SuperH on-chip PCIC emulation.
- *
- * Copyright (c) 2008 Takashi YOSHII
- *
- * 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/sysbus.h"
-#include "hw/sh4/sh.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_host.h"
-#include "qemu/bswap.h"
-#include "exec/address-spaces.h"
-
-typedef struct SHPCIState {
-    SysBusDevice busdev;
-    PCIBus *bus;
-    PCIDevice *dev;
-    qemu_irq irq[4];
-    MemoryRegion memconfig_p4;
-    MemoryRegion memconfig_a7;
-    MemoryRegion isa;
-    uint32_t par;
-    uint32_t mbr;
-    uint32_t iobr;
-} SHPCIState;
-
-static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
-                              unsigned size)
-{
-    SHPCIState *pcic = p;
-    switch(addr) {
-    case 0 ... 0xfc:
-        cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
-        break;
-    case 0x1c0:
-        pcic->par = val;
-        break;
-    case 0x1c4:
-        pcic->mbr = val & 0xff000001;
-        break;
-    case 0x1c8:
-        if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
-            memory_region_del_subregion(get_system_memory(), &pcic->isa);
-            pcic->iobr = val & 0xfffc0001;
-            memory_region_add_subregion(get_system_memory(),
-                                        pcic->iobr & 0xfffc0000, &pcic->isa);
-        }
-        break;
-    case 0x220:
-        pci_data_write(pcic->bus, pcic->par, val, 4);
-        break;
-    }
-}
-
-static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
-                                 unsigned size)
-{
-    SHPCIState *pcic = p;
-    switch(addr) {
-    case 0 ... 0xfc:
-        return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
-    case 0x1c0:
-        return pcic->par;
-    case 0x1c4:
-        return pcic->mbr;
-    case 0x1c8:
-        return pcic->iobr;
-    case 0x220:
-        return pci_data_read(pcic->bus, pcic->par, 4);
-    }
-    return 0;
-}
-
-static const MemoryRegionOps sh_pci_reg_ops = {
-    .read = sh_pci_reg_read,
-    .write = sh_pci_reg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static int sh_pci_map_irq(PCIDevice *d, int irq_num)
-{
-    return (d->devfn >> 3);
-}
-
-static void sh_pci_set_irq(void *opaque, int irq_num, int level)
-{
-    qemu_irq *pic = opaque;
-
-    qemu_set_irq(pic[irq_num], level);
-}
-
-static int sh_pci_device_init(SysBusDevice *dev)
-{
-    SHPCIState *s;
-    int i;
-
-    s = FROM_SYSBUS(SHPCIState, dev);
-    for (i = 0; i < 4; i++) {
-        sysbus_init_irq(dev, &s->irq[i]);
-    }
-    s->bus = pci_register_bus(&s->busdev.qdev, "pci",
-                              sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq,
-                              get_system_memory(),
-                              get_system_io(),
-                              PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
-    memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s,
-                          "sh_pci", 0x224);
-    memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
-                             0, 0x224);
-    isa_mmio_setup(&s->isa, 0x40000);
-    sysbus_init_mmio(dev, &s->memconfig_p4);
-    sysbus_init_mmio(dev, &s->memconfig_a7);
-    s->iobr = 0xfe240000;
-    memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
-
-    s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
-    return 0;
-}
-
-static int sh_pci_host_init(PCIDevice *d)
-{
-    pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
-    pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
-                 PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
-    return 0;
-}
-
-static void sh_pci_host_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = sh_pci_host_init;
-    k->vendor_id = PCI_VENDOR_ID_HITACHI;
-    k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
-}
-
-static const TypeInfo sh_pci_host_info = {
-    .name          = "sh_pci_host",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .class_init    = sh_pci_host_class_init,
-};
-
-static void sh_pci_device_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = sh_pci_device_init;
-}
-
-static const TypeInfo sh_pci_device_info = {
-    .name          = "sh_pci",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SHPCIState),
-    .class_init    = sh_pci_device_class_init,
-};
-
-static void sh_pci_register_types(void)
-{
-    type_register_static(&sh_pci_device_info);
-    type_register_static(&sh_pci_host_info);
-}
-
-type_init(sh_pci_register_types)
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
deleted file mode 100644 (file)
index 62ff323..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * QEMU sPAPR PCI host originated from Uninorth PCI host
- *
- * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
- * Copyright (C) 2011 David Gibson, IBM Corporation.
- *
- * 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/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/msix.h"
-#include "hw/pci/pci_host.h"
-#include "hw/ppc/spapr.h"
-#include "hw/pci-host/spapr.h"
-#include "exec/address-spaces.h"
-#include <libfdt.h>
-#include "trace.h"
-
-#include "hw/pci/pci_bus.h"
-
-/* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
-#define RTAS_QUERY_FN           0
-#define RTAS_CHANGE_FN          1
-#define RTAS_RESET_FN           2
-#define RTAS_CHANGE_MSI_FN      3
-#define RTAS_CHANGE_MSIX_FN     4
-
-/* Interrupt types to return on RTAS_CHANGE_* */
-#define RTAS_TYPE_MSI           1
-#define RTAS_TYPE_MSIX          2
-
-static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
-{
-    sPAPRPHBState *sphb;
-
-    QLIST_FOREACH(sphb, &spapr->phbs, list) {
-        if (sphb->buid != buid) {
-            continue;
-        }
-        return sphb;
-    }
-
-    return NULL;
-}
-
-static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
-                           uint32_t config_addr)
-{
-    sPAPRPHBState *sphb = find_phb(spapr, buid);
-    PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
-    BusState *bus = BUS(phb->bus);
-    BusChild *kid;
-    int devfn = (config_addr >> 8) & 0xFF;
-
-    if (!phb) {
-        return NULL;
-    }
-
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        PCIDevice *dev = (PCIDevice *)kid->child;
-        if (dev->devfn == devfn) {
-            return dev;
-        }
-    }
-
-    return NULL;
-}
-
-static uint32_t rtas_pci_cfgaddr(uint32_t arg)
-{
-    /* This handles the encoding of extended config space addresses */
-    return ((arg >> 20) & 0xf00) | (arg & 0xff);
-}
-
-static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
-                                   uint32_t addr, uint32_t size,
-                                   target_ulong rets)
-{
-    PCIDevice *pci_dev;
-    uint32_t val;
-
-    if ((size != 1) && (size != 2) && (size != 4)) {
-        /* access must be 1, 2 or 4 bytes */
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    pci_dev = find_dev(spapr, buid, addr);
-    addr = rtas_pci_cfgaddr(addr);
-
-    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
-        /* Access must be to a valid device, within bounds and
-         * naturally aligned */
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    val = pci_host_config_read_common(pci_dev, addr,
-                                      pci_config_size(pci_dev), size);
-
-    rtas_st(rets, 0, 0);
-    rtas_st(rets, 1, val);
-}
-
-static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
-                                     uint32_t token, uint32_t nargs,
-                                     target_ulong args,
-                                     uint32_t nret, target_ulong rets)
-{
-    uint64_t buid;
-    uint32_t size, addr;
-
-    if ((nargs != 4) || (nret != 2)) {
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    size = rtas_ld(args, 3);
-    addr = rtas_ld(args, 0);
-
-    finish_read_pci_config(spapr, buid, addr, size, rets);
-}
-
-static void rtas_read_pci_config(sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    uint32_t size, addr;
-
-    if ((nargs != 2) || (nret != 2)) {
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    size = rtas_ld(args, 1);
-    addr = rtas_ld(args, 0);
-
-    finish_read_pci_config(spapr, 0, addr, size, rets);
-}
-
-static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
-                                    uint32_t addr, uint32_t size,
-                                    uint32_t val, target_ulong rets)
-{
-    PCIDevice *pci_dev;
-
-    if ((size != 1) && (size != 2) && (size != 4)) {
-        /* access must be 1, 2 or 4 bytes */
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    pci_dev = find_dev(spapr, buid, addr);
-    addr = rtas_pci_cfgaddr(addr);
-
-    if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
-        /* Access must be to a valid device, within bounds and
-         * naturally aligned */
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    pci_host_config_write_common(pci_dev, addr, pci_config_size(pci_dev),
-                                 val, size);
-
-    rtas_st(rets, 0, 0);
-}
-
-static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
-                                      uint32_t token, uint32_t nargs,
-                                      target_ulong args,
-                                      uint32_t nret, target_ulong rets)
-{
-    uint64_t buid;
-    uint32_t val, size, addr;
-
-    if ((nargs != 5) || (nret != 1)) {
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-    buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    val = rtas_ld(args, 4);
-    size = rtas_ld(args, 3);
-    addr = rtas_ld(args, 0);
-
-    finish_write_pci_config(spapr, buid, addr, size, val, rets);
-}
-
-static void rtas_write_pci_config(sPAPREnvironment *spapr,
-                                  uint32_t token, uint32_t nargs,
-                                  target_ulong args,
-                                  uint32_t nret, target_ulong rets)
-{
-    uint32_t val, size, addr;
-
-    if ((nargs != 3) || (nret != 1)) {
-        rtas_st(rets, 0, -1);
-        return;
-    }
-
-
-    val = rtas_ld(args, 2);
-    size = rtas_ld(args, 1);
-    addr = rtas_ld(args, 0);
-
-    finish_write_pci_config(spapr, 0, addr, size, val, rets);
-}
-
-/*
- * Find an entry with config_addr or returns the empty one if not found AND
- * alloc_new is set.
- * At the moment the msi_table entries are never released so there is
- * no point to look till the end of the list if we need to find the free entry.
- */
-static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr,
-                             bool alloc_new)
-{
-    int i;
-
-    for (i = 0; i < SPAPR_MSIX_MAX_DEVS; ++i) {
-        if (!phb->msi_table[i].nvec) {
-            break;
-        }
-        if (phb->msi_table[i].config_addr == config_addr) {
-            return i;
-        }
-    }
-    if ((i < SPAPR_MSIX_MAX_DEVS) && alloc_new) {
-        trace_spapr_pci_msi("Allocating new MSI config", i, config_addr);
-        return i;
-    }
-
-    return -1;
-}
-
-/*
- * Set MSI/MSIX message data.
- * This is required for msi_notify()/msix_notify() which
- * will write at the addresses via spapr_msi_write().
- */
-static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr,
-                             bool msix, unsigned req_num)
-{
-    unsigned i;
-    MSIMessage msg = { .address = addr, .data = 0 };
-
-    if (!msix) {
-        msi_set_message(pdev, msg);
-        trace_spapr_pci_msi_setup(pdev->name, 0, msg.address);
-        return;
-    }
-
-    for (i = 0; i < req_num; ++i) {
-        msg.address = addr | (i << 2);
-        msix_set_message(pdev, i, msg);
-        trace_spapr_pci_msi_setup(pdev->name, i, msg.address);
-    }
-}
-
-static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
-                                uint32_t token, uint32_t nargs,
-                                target_ulong args, uint32_t nret,
-                                target_ulong rets)
-{
-    uint32_t config_addr = rtas_ld(args, 0);
-    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    unsigned int func = rtas_ld(args, 3);
-    unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */
-    unsigned int seq_num = rtas_ld(args, 5);
-    unsigned int ret_intr_type;
-    int ndev, irq;
-    sPAPRPHBState *phb = NULL;
-    PCIDevice *pdev = NULL;
-
-    switch (func) {
-    case RTAS_CHANGE_MSI_FN:
-    case RTAS_CHANGE_FN:
-        ret_intr_type = RTAS_TYPE_MSI;
-        break;
-    case RTAS_CHANGE_MSIX_FN:
-        ret_intr_type = RTAS_TYPE_MSIX;
-        break;
-    default:
-        fprintf(stderr, "rtas_ibm_change_msi(%u) is not implemented\n", func);
-        rtas_st(rets, 0, -3); /* Parameter error */
-        return;
-    }
-
-    /* Fins sPAPRPHBState */
-    phb = find_phb(spapr, buid);
-    if (phb) {
-        pdev = find_dev(spapr, buid, config_addr);
-    }
-    if (!phb || !pdev) {
-        rtas_st(rets, 0, -3); /* Parameter error */
-        return;
-    }
-
-    /* Releasing MSIs */
-    if (!req_num) {
-        ndev = spapr_msicfg_find(phb, config_addr, false);
-        if (ndev < 0) {
-            trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
-            rtas_st(rets, 0, -1); /* Hardware error */
-            return;
-        }
-        trace_spapr_pci_msi("Released MSIs", ndev, config_addr);
-        rtas_st(rets, 0, 0);
-        rtas_st(rets, 1, 0);
-        return;
-    }
-
-    /* Enabling MSI */
-
-    /* Find a device number in the map to add or reuse the existing one */
-    ndev = spapr_msicfg_find(phb, config_addr, true);
-    if (ndev >= SPAPR_MSIX_MAX_DEVS || ndev < 0) {
-        fprintf(stderr, "No free entry for a new MSI device\n");
-        rtas_st(rets, 0, -1); /* Hardware error */
-        return;
-    }
-    trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);
-
-    /* Check if there is an old config and MSI number has not changed */
-    if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
-        /* Unexpected behaviour */
-        fprintf(stderr, "Cannot reuse MSI config for device#%d", ndev);
-        rtas_st(rets, 0, -1); /* Hardware error */
-        return;
-    }
-
-    /* There is no cached config, allocate MSIs */
-    if (!phb->msi_table[ndev].nvec) {
-        irq = spapr_allocate_irq_block(req_num, false);
-        if (irq < 0) {
-            fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
-            rtas_st(rets, 0, -1); /* Hardware error */
-            return;
-        }
-        phb->msi_table[ndev].irq = irq;
-        phb->msi_table[ndev].nvec = req_num;
-        phb->msi_table[ndev].config_addr = config_addr;
-    }
-
-    /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */
-    spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16),
-                     ret_intr_type == RTAS_TYPE_MSIX, req_num);
-
-    rtas_st(rets, 0, 0);
-    rtas_st(rets, 1, req_num);
-    rtas_st(rets, 2, ++seq_num);
-    rtas_st(rets, 3, ret_intr_type);
-
-    trace_spapr_pci_rtas_ibm_change_msi(func, req_num);
-}
-
-static void rtas_ibm_query_interrupt_source_number(sPAPREnvironment *spapr,
-                                                   uint32_t token,
-                                                   uint32_t nargs,
-                                                   target_ulong args,
-                                                   uint32_t nret,
-                                                   target_ulong rets)
-{
-    uint32_t config_addr = rtas_ld(args, 0);
-    uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
-    unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
-    int ndev;
-    sPAPRPHBState *phb = NULL;
-
-    /* Fins sPAPRPHBState */
-    phb = find_phb(spapr, buid);
-    if (!phb) {
-        rtas_st(rets, 0, -3); /* Parameter error */
-        return;
-    }
-
-    /* Find device descriptor and start IRQ */
-    ndev = spapr_msicfg_find(phb, config_addr, false);
-    if (ndev < 0) {
-        trace_spapr_pci_msi("MSI has not been enabled", -1, config_addr);
-        rtas_st(rets, 0, -1); /* Hardware error */
-        return;
-    }
-
-    intr_src_num = phb->msi_table[ndev].irq + ioa_intr_num;
-    trace_spapr_pci_rtas_ibm_query_interrupt_source_number(ioa_intr_num,
-                                                           intr_src_num);
-
-    rtas_st(rets, 0, 0);
-    rtas_st(rets, 1, intr_src_num);
-    rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */
-}
-
-static int pci_spapr_swizzle(int slot, int pin)
-{
-    return (slot + pin) % PCI_NUM_PINS;
-}
-
-static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
-{
-    /*
-     * Here we need to convert pci_dev + irq_num to some unique value
-     * which is less than number of IRQs on the specific bus (4).  We
-     * use standard PCI swizzling, that is (slot number + pin number)
-     * % 4.
-     */
-    return pci_spapr_swizzle(PCI_SLOT(pci_dev->devfn), irq_num);
-}
-
-static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
-{
-    /*
-     * Here we use the number returned by pci_spapr_map_irq to find a
-     * corresponding qemu_irq.
-     */
-    sPAPRPHBState *phb = opaque;
-
-    trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq);
-    qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
-}
-
-static uint64_t spapr_io_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    switch (size) {
-    case 1:
-        return cpu_inb(addr);
-    case 2:
-        return cpu_inw(addr);
-    case 4:
-        return cpu_inl(addr);
-    }
-    assert(0);
-}
-
-static void spapr_io_write(void *opaque, hwaddr addr,
-                           uint64_t data, unsigned size)
-{
-    switch (size) {
-    case 1:
-        cpu_outb(addr, data);
-        return;
-    case 2:
-        cpu_outw(addr, data);
-        return;
-    case 4:
-        cpu_outl(addr, data);
-        return;
-    }
-    assert(0);
-}
-
-static const MemoryRegionOps spapr_io_ops = {
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .read = spapr_io_read,
-    .write = spapr_io_write
-};
-
-/*
- * MSI/MSIX memory region implementation.
- * The handler handles both MSI and MSIX.
- * For MSI-X, the vector number is encoded as a part of the address,
- * data is set to 0.
- * For MSI, the vector number is encoded in least bits in data.
- */
-static void spapr_msi_write(void *opaque, hwaddr addr,
-                            uint64_t data, unsigned size)
-{
-    sPAPRPHBState *phb = opaque;
-    int ndev = addr >> 16;
-    int vec = ((addr & 0xFFFF) >> 2) | data;
-    uint32_t irq = phb->msi_table[ndev].irq + vec;
-
-    trace_spapr_pci_msi_write(addr, data, irq);
-
-    qemu_irq_pulse(xics_get_qirq(spapr->icp, irq));
-}
-
-static const MemoryRegionOps spapr_msi_ops = {
-    /* There is no .read as the read result is undefined by PCI spec */
-    .read = NULL,
-    .write = spapr_msi_write,
-    .endianness = DEVICE_LITTLE_ENDIAN
-};
-
-/*
- * PHB PCI device
- */
-static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
-                                            int devfn)
-{
-    sPAPRPHBState *phb = opaque;
-
-    return phb->dma;
-}
-
-static int spapr_phb_init(SysBusDevice *s)
-{
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
-    PCIHostState *phb = PCI_HOST_BRIDGE(s);
-    const char *busname;
-    char *namebuf;
-    int i;
-    PCIBus *bus;
-
-    if (sphb->index != -1) {
-        hwaddr windows_base;
-
-        if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
-            || (sphb->mem_win_addr != -1)
-            || (sphb->io_win_addr != -1)
-            || (sphb->msi_win_addr != -1)) {
-            fprintf(stderr, "Either \"index\" or other parameters must"
-                    " be specified for PAPR PHB, not both\n");
-            return -1;
-        }
-
-        sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
-        sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index;
-
-        windows_base = SPAPR_PCI_WINDOW_BASE
-            + sphb->index * SPAPR_PCI_WINDOW_SPACING;
-        sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF;
-        sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF;
-        sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF;
-    }
-
-    if (sphb->buid == -1) {
-        fprintf(stderr, "BUID not specified for PHB\n");
-        return -1;
-    }
-
-    if (sphb->dma_liobn == -1) {
-        fprintf(stderr, "LIOBN not specified for PHB\n");
-        return -1;
-    }
-
-    if (sphb->mem_win_addr == -1) {
-        fprintf(stderr, "Memory window address not specified for PHB\n");
-        return -1;
-    }
-
-    if (sphb->io_win_addr == -1) {
-        fprintf(stderr, "IO window address not specified for PHB\n");
-        return -1;
-    }
-
-    if (sphb->msi_win_addr == -1) {
-        fprintf(stderr, "MSI window address not specified for PHB\n");
-        return -1;
-    }
-
-    if (find_phb(spapr, sphb->buid)) {
-        fprintf(stderr, "PCI host bridges must have unique BUIDs\n");
-        return -1;
-    }
-
-    sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
-
-    namebuf = alloca(strlen(sphb->dtbusname) + 32);
-
-    /* Initialize memory regions */
-    sprintf(namebuf, "%s.mmio", sphb->dtbusname);
-    memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
-
-    sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
-    memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
-                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
-    memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
-                                &sphb->memwindow);
-
-    /* On ppc, we only have MMIO no specific IO space from the CPU
-     * perspective.  In theory we ought to be able to embed the PCI IO
-     * memory region direction in the system memory space.  However,
-     * if any of the IO BAR subregions use the old_portio mechanism,
-     * that won't be processed properly unless accessed from the
-     * system io address space.  This hack to bounce things via
-     * system_io works around the problem until all the users of
-     * old_portion are updated */
-    sprintf(namebuf, "%s.io", sphb->dtbusname);
-    memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
-    /* FIXME: fix to support multiple PHBs */
-    memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
-
-    sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
-    memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
-                          namebuf, SPAPR_PCI_IO_WIN_SIZE);
-    memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
-                                &sphb->iowindow);
-
-    /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
-     * we need to allocate some memory to catch those writes coming
-     * from msi_notify()/msix_notify() */
-    if (msi_supported) {
-        sprintf(namebuf, "%s.msi", sphb->dtbusname);
-        memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
-                              namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
-        memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
-                                    &sphb->msiwindow);
-    }
-
-    /*
-     * Selecting a busname is more complex than you'd think, due to
-     * interacting constraints.  If the user has specified an id
-     * explicitly for the phb , then we want to use the qdev default
-     * of naming the bus based on the bridge device (so the user can
-     * then assign devices to it in the way they expect).  For the
-     * first / default PCI bus (index=0) we want to use just "pci"
-     * because libvirt expects there to be a bus called, simply,
-     * "pci".  Otherwise, we use the same name as in the device tree,
-     * since it's unique by construction, and makes the guest visible
-     * BUID clear.
-     */
-    if (s->qdev.id) {
-        busname = NULL;
-    } else if (sphb->index == 0) {
-        busname = "pci";
-    } else {
-        busname = sphb->dtbusname;
-    }
-    bus = pci_register_bus(DEVICE(s), busname,
-                           pci_spapr_set_irq, pci_spapr_map_irq, sphb,
-                           &sphb->memspace, &sphb->iospace,
-                           PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
-    phb->bus = bus;
-
-    sphb->dma_window_start = 0;
-    sphb->dma_window_size = 0x40000000;
-    sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
-    if (!sphb->dma) {
-        fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
-        return -1;
-    }
-    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
-
-    QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
-
-    /* Initialize the LSI table */
-    for (i = 0; i < PCI_NUM_PINS; i++) {
-        uint32_t irq;
-
-        irq = spapr_allocate_lsi(0);
-        if (!irq) {
-            return -1;
-        }
-
-        sphb->lsi_table[i].irq = irq;
-    }
-
-    return 0;
-}
-
-static void spapr_phb_reset(DeviceState *qdev)
-{
-    SysBusDevice *s = SYS_BUS_DEVICE(qdev);
-    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
-
-    /* Reset the IOMMU state */
-    spapr_tce_reset(sphb->dma);
-}
-
-static Property spapr_phb_properties[] = {
-    DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
-    DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
-    DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
-    DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
-    DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size,
-                      SPAPR_PCI_MMIO_WIN_SIZE),
-    DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
-    DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size,
-                      SPAPR_PCI_IO_WIN_SIZE),
-    DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void spapr_phb_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    sdc->init = spapr_phb_init;
-    dc->props = spapr_phb_properties;
-    dc->reset = spapr_phb_reset;
-}
-
-static const TypeInfo spapr_phb_info = {
-    .name          = TYPE_SPAPR_PCI_HOST_BRIDGE,
-    .parent        = TYPE_PCI_HOST_BRIDGE,
-    .instance_size = sizeof(sPAPRPHBState),
-    .class_init    = spapr_phb_class_init,
-};
-
-PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
-    qdev_prop_set_uint32(dev, "index", index);
-    qdev_init_nofail(dev);
-
-    return PCI_HOST_BRIDGE(dev);
-}
-
-/* Macros to operate with address in OF binding to PCI */
-#define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
-#define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
-#define b_p(x)          b_x((x), 30, 1) /* 1 if prefetchable */
-#define b_t(x)          b_x((x), 29, 1) /* 1 if the address is aliased */
-#define b_ss(x)         b_x((x), 24, 2) /* the space code */
-#define b_bbbbbbbb(x)   b_x((x), 16, 8) /* bus number */
-#define b_ddddd(x)      b_x((x), 11, 5) /* device number */
-#define b_fff(x)        b_x((x), 8, 3)  /* function number */
-#define b_rrrrrrrr(x)   b_x((x), 0, 8)  /* register number */
-
-int spapr_populate_pci_dt(sPAPRPHBState *phb,
-                          uint32_t xics_phandle,
-                          void *fdt)
-{
-    int bus_off, i, j;
-    char nodename[256];
-    uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
-    struct {
-        uint32_t hi;
-        uint64_t child;
-        uint64_t parent;
-        uint64_t size;
-    } QEMU_PACKED ranges[] = {
-        {
-            cpu_to_be32(b_ss(1)), cpu_to_be64(0),
-            cpu_to_be64(phb->io_win_addr),
-            cpu_to_be64(memory_region_size(&phb->iospace)),
-        },
-        {
-            cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET),
-            cpu_to_be64(phb->mem_win_addr),
-            cpu_to_be64(memory_region_size(&phb->memwindow)),
-        },
-    };
-    uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
-    uint32_t interrupt_map_mask[] = {
-        cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
-    uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
-
-    /* Start populating the FDT */
-    sprintf(nodename, "pci@%" PRIx64, phb->buid);
-    bus_off = fdt_add_subnode(fdt, 0, nodename);
-    if (bus_off < 0) {
-        return bus_off;
-    }
-
-#define _FDT(exp) \
-    do { \
-        int ret = (exp);                                           \
-        if (ret < 0) {                                             \
-            return ret;                                            \
-        }                                                          \
-    } while (0)
-
-    /* Write PHB properties */
-    _FDT(fdt_setprop_string(fdt, bus_off, "device_type", "pci"));
-    _FDT(fdt_setprop_string(fdt, bus_off, "compatible", "IBM,Logical_PHB"));
-    _FDT(fdt_setprop_cell(fdt, bus_off, "#address-cells", 0x3));
-    _FDT(fdt_setprop_cell(fdt, bus_off, "#size-cells", 0x2));
-    _FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1));
-    _FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0));
-    _FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range)));
-    _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges)));
-    _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
-    _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
-
-    /* Build the interrupt-map, this must matches what is done
-     * in pci_spapr_map_irq
-     */
-    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
-                     &interrupt_map_mask, sizeof(interrupt_map_mask)));
-    for (i = 0; i < PCI_SLOT_MAX; i++) {
-        for (j = 0; j < PCI_NUM_PINS; j++) {
-            uint32_t *irqmap = interrupt_map[i*PCI_NUM_PINS + j];
-            int lsi_num = pci_spapr_swizzle(i, j);
-
-            irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
-            irqmap[1] = 0;
-            irqmap[2] = 0;
-            irqmap[3] = cpu_to_be32(j+1);
-            irqmap[4] = cpu_to_be32(xics_phandle);
-            irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq);
-            irqmap[6] = cpu_to_be32(0x8);
-        }
-    }
-    /* Write interrupt map */
-    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
-                     sizeof(interrupt_map)));
-
-    spapr_dma_dt(fdt, bus_off, "ibm,dma-window",
-                 phb->dma_liobn, phb->dma_window_start,
-                 phb->dma_window_size);
-
-    return 0;
-}
-
-void spapr_pci_rtas_init(void)
-{
-    spapr_rtas_register("read-pci-config", rtas_read_pci_config);
-    spapr_rtas_register("write-pci-config", rtas_write_pci_config);
-    spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
-    spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
-    if (msi_supported) {
-        spapr_rtas_register("ibm,query-interrupt-source-number",
-                            rtas_ibm_query_interrupt_source_number);
-        spapr_rtas_register("ibm,change-msi", rtas_ibm_change_msi);
-    }
-}
-
-static void spapr_pci_register_types(void)
-{
-    type_register_static(&spapr_phb_info);
-}
-
-type_init(spapr_pci_register_types)
index 178464ba5466c6016eb62de58819185e9ebf997d..a84cfe3ec79c845ffe9b439e74b09df7aac1e0b7 100644 (file)
@@ -1,5 +1 @@
-obj-y = apb_pci.o
-
-obj-y := $(addprefix ../,$(obj-y))
-
 obj-y += sun4u.o
index 6b50b5f34a04185a4015bcaac720f66ff703691e..e182c820ac71084e08602b0d346d21aed3fea946 100644 (file)
@@ -28,7 +28,6 @@
 #include "hw/sysbus.h"
 #include "hw/i386/pc.h"
 #include "hw/isa/apm.h"
-#include "hw/i386/apic.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pcie_host.h"
 #include "hw/acpi/acpi.h"