aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-11-06 17:52:14 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-11-06 17:52:14 +0000
commit80d1c10b2243866a86d0c1eb919b94aadda2aba0 (patch)
tree526291a60c9d90ad7263fe449e6a8a97241d665f
parent4570c2e5fa994d56d328344d8d127da8b1c27b59 (diff)
parent48bc99a09cb160a3a2612c4bd5a8a225ed7bf6fb (diff)
downloadqemu-80d1c10b2243866a86d0c1eb919b94aadda2aba0.tar.gz
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/mips-next-20191105' into staging
The i440FX northbridge is only used by the PC machine, while the PIIX southbridge is also used by the Malta MIPS machine. Split the PIIX3 southbridge from i440FX northbridge. # gpg: Signature made Tue 05 Nov 2019 22:48:12 GMT # gpg: using RSA key 89C1E78F601EE86C867495CBA2A3FD6EDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (Phil) <philmd@redhat.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 89C1 E78F 601E E86C 8674 95CB A2A3 FD6E DEAD C0DE * remotes/philmd-gitlab/tags/mips-next-20191105: (21 commits) hw/pci-host/i440fx: Remove the last PIIX3 traces hw/pci-host: Rename incorrectly named 'piix' as 'i440fx' hw/pci-host/piix: Extract PIIX3 functions to hw/isa/piix3.c hw/pci-host/piix: Fix code style issues hw/pci-host/piix: Move i440FX declarations to hw/pci-host/i440fx.h hw/pci-host/piix: Define and use the PIIX IRQ Route Control Registers hw/pci-host/piix: Move RCR_IOPORT register definition hw/pci-host/piix: Extract piix3_create() hw/i386: Remove obsolete LoadStateHandler::load_state_old handlers hw/isa/piix4: Move piix4_create() to hw/isa/piix4.c hw/mips/mips_malta: Extract the PIIX4 creation code as piix4_create() hw/mips/mips_malta: Create IDE hard drive array dynamically piix4: Add a MC146818 RTC Controller as specified in datasheet piix4: Add an i8254 PIT Controller as specified in datasheet piix4: Add an i8257 DMA Controller as specified in datasheet piix4: Rename PIIX4 object to piix4-isa Revert "irq: introduce qemu_irq_proxy()" piix4: Add an i8259 Interrupt Controller as specified in datasheet piix4: Add the Reset Control Register MAINTAINERS: Keep PIIX4 South Bridge separate from PC Chipsets ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS14
-rw-r--r--Makefile3
-rw-r--r--hw/acpi/pcihp.c2
-rw-r--r--hw/acpi/piix4.c42
-rw-r--r--hw/core/irq.c14
-rw-r--r--hw/i386/Kconfig3
-rw-r--r--hw/i386/acpi-build.c5
-rw-r--r--hw/i386/pc_piix.c10
-rw-r--r--hw/i386/xen/xen-hvm.c5
-rw-r--r--hw/intc/apic_common.c49
-rw-r--r--hw/isa/Kconfig4
-rw-r--r--hw/isa/Makefile.objs1
-rw-r--r--hw/isa/piix3.c399
-rw-r--r--hw/isa/piix4.c143
-rw-r--r--hw/mips/gt64xxx_pci.c5
-rw-r--r--hw/mips/mips_malta.c46
-rw-r--r--hw/pci-host/Kconfig3
-rw-r--r--hw/pci-host/Makefile.objs2
-rw-r--r--hw/pci-host/i440fx.c (renamed from hw/pci-host/piix.c)424
-rw-r--r--hw/timer/i8254_common.c40
-rw-r--r--include/hw/acpi/piix4.h6
-rw-r--r--include/hw/i386/pc.h37
-rw-r--r--include/hw/irq.h5
-rw-r--r--include/hw/isa/isa.h2
-rw-r--r--include/hw/pci-host/i440fx.h36
-rw-r--r--include/hw/southbridge/piix.h74
-rw-r--r--stubs/pci-host-piix.c3
27 files changed, 697 insertions, 680 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index c2a68555aef..363e72a467f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1241,18 +1241,19 @@ M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
S: Supported
F: include/hw/i386/
F: hw/i386/
-F: hw/pci-host/piix.c
+F: hw/pci-host/i440fx.c
F: hw/pci-host/q35.c
F: hw/pci-host/pam.c
+F: include/hw/pci-host/i440fx.h
F: include/hw/pci-host/q35.h
F: include/hw/pci-host/pam.h
-F: hw/isa/piix4.c
+F: hw/isa/piix3.c
F: hw/isa/lpc_ich9.c
F: hw/i2c/smbus_ich9.c
F: hw/acpi/piix4.c
F: hw/acpi/ich9.c
F: include/hw/acpi/ich9.h
-F: include/hw/acpi/piix4.h
+F: include/hw/southbridge/piix.h
F: hw/misc/sga.c
F: hw/isa/apm.c
F: include/hw/isa/apm.h
@@ -1753,6 +1754,13 @@ F: hw/display/edid*
F: include/hw/display/edid.h
F: qemu-edid.c
+PIIX4 South Bridge (i82371AB)
+M: Hervé Poussineau <hpoussin@reactos.org>
+M: Philippe Mathieu-Daudé <f4bug@amsat.org>
+S: Maintained
+F: hw/isa/piix4.c
+F: include/hw/southbridge/piix.h
+
Firmware configuration (fw_cfg)
M: Philippe Mathieu-Daudé <philmd@redhat.com>
R: Laszlo Ersek <lersek@redhat.com>
diff --git a/Makefile b/Makefile
index bd6376d295f..aa9d1a42aa9 100644
--- a/Makefile
+++ b/Makefile
@@ -390,7 +390,8 @@ MINIKCONF_ARGS = \
CONFIG_LINUX=$(CONFIG_LINUX) \
CONFIG_PVRDMA=$(CONFIG_PVRDMA)
-MINIKCONF_INPUTS = $(SRC_PATH)/Kconfig.host $(SRC_PATH)/hw/Kconfig
+MINIKCONF_INPUTS = $(SRC_PATH)/Kconfig.host $(SRC_PATH)/hw/Kconfig \
+ $(wildcard $(SRC_PATH)/hw/*/Kconfig)
MINIKCONF = $(PYTHON) $(SRC_PATH)/scripts/minikconf.py \
$(SUBDIR_DEVICES_MAK): %/config-devices.mak: default-configs/%.mak $(MINIKCONF_INPUTS) $(BUILD_DIR)/config-host.mak
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 82d295b6e81..8413348a33f 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -27,7 +27,7 @@
#include "qemu/osdep.h"
#include "hw/acpi/pcihp.h"
-#include "hw/i386/pc.h"
+#include "hw/pci-host/i440fx.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bridge.h"
#include "hw/acpi/acpi.h"
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 4e079b39bd6..93aec2dd2ce 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "hw/i386/pc.h"
+#include "hw/southbridge/piix.h"
#include "hw/irq.h"
#include "hw/isa/apm.h"
#include "hw/i2c/pm_smbus.h"
@@ -32,7 +33,6 @@
#include "qapi/error.h"
#include "qemu/range.h"
#include "exec/address-spaces.h"
-#include "hw/acpi/piix4.h"
#include "hw/acpi/pcihp.h"
#include "hw/acpi/cpu_hotplug.h"
#include "hw/acpi/cpu.h"
@@ -41,7 +41,6 @@
#include "hw/acpi/memory_hotplug.h"
#include "hw/acpi/acpi_dev_interface.h"
#include "hw/xen/xen.h"
-#include "migration/qemu-file-types.h"
#include "migration/vmstate.h"
#include "hw/core/cpu.h"
#include "trace.h"
@@ -204,43 +203,6 @@ static const VMStateDescription vmstate_pci_status = {
}
};
-static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
-{
- PIIX4PMState *s = opaque;
- int ret, i;
- uint16_t temp;
-
- ret = pci_device_load(PCI_DEVICE(s), f);
- if (ret < 0) {
- return ret;
- }
- qemu_get_be16s(f, &s->ar.pm1.evt.sts);
- qemu_get_be16s(f, &s->ar.pm1.evt.en);
- qemu_get_be16s(f, &s->ar.pm1.cnt.cnt);
-
- ret = vmstate_load_state(f, &vmstate_apm, &s->apm, 1);
- if (ret) {
- return ret;
- }
-
- timer_get(f, s->ar.tmr.timer);
- qemu_get_sbe64s(f, &s->ar.tmr.overflow_time);
-
- qemu_get_be16s(f, (uint16_t *)s->ar.gpe.sts);
- for (i = 0; i < 3; i++) {
- qemu_get_be16s(f, &temp);
- }
-
- qemu_get_be16s(f, (uint16_t *)s->ar.gpe.en);
- for (i = 0; i < 3; i++) {
- qemu_get_be16s(f, &temp);
- }
-
- ret = vmstate_load_state(f, &vmstate_pci_status,
- &s->acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], 1);
- return ret;
-}
-
static bool vmstate_test_use_acpi_pci_hotplug(void *opaque, int version_id)
{
PIIX4PMState *s = opaque;
@@ -312,8 +274,6 @@ static const VMStateDescription vmstate_acpi = {
.name = "piix4_pm",
.version_id = 3,
.minimum_version_id = 3,
- .minimum_version_id_old = 1,
- .load_state_old = acpi_load_old,
.post_load = vmstate_acpi_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, PIIX4PMState),
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 7cc0295d0e8..fb3045b912e 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -120,20 +120,6 @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
return qemu_allocate_irq(qemu_splitirq, s, 0);
}
-static void proxy_irq_handler(void *opaque, int n, int level)
-{
- qemu_irq **target = opaque;
-
- if (*target) {
- qemu_set_irq((*target)[n], level);
- }
-}
-
-qemu_irq *qemu_irq_proxy(qemu_irq **target, int n)
-{
- return qemu_allocate_irqs(proxy_irq_handler, target, n);
-}
-
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
{
int i;
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index b25bb6d78a7..5a494342eaa 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -60,7 +60,8 @@ config I440FX
select PC_PCI
select PC_ACPI
select ACPI_SMBUS
- select PCI_PIIX
+ select PCI_I440FX
+ select PIIX3
select IDE_PIIX
select DIMM
select SMBIOS
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9dd3dbb16ce..266d9b534b6 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -34,7 +34,6 @@
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/cpu.h"
-#include "hw/acpi/piix4.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/acpi/bios-linker-loader.h"
#include "hw/isa/isa.h"
@@ -52,7 +51,7 @@
#include "sysemu/reset.h"
/* Supported chipsets: */
-#include "hw/acpi/piix4.h"
+#include "hw/southbridge/piix.h"
#include "hw/acpi/pcihp.h"
#include "hw/i386/ich9.h"
#include "hw/pci/pci_bus.h"
@@ -210,7 +209,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
/* The above need not be conditional on machine type because the reset port
* happens to be the same on PIIX (pc) and ICH9 (q35). */
- QEMU_BUILD_BUG_ON(ICH9_RST_CNT_IOPORT != RCR_IOPORT);
+ QEMU_BUILD_BUG_ON(ICH9_RST_CNT_IOPORT != PIIX_RCR_IOPORT);
/* Fill in optional s3/s4 related properties */
o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c15929a1f5a..2aefa3b8dfe 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -30,6 +30,8 @@
#include "hw/i386/x86.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
+#include "hw/pci-host/i440fx.h"
+#include "hw/southbridge/piix.h"
#include "hw/display/ramfb.h"
#include "hw/firmware/smbios.h"
#include "hw/pci/pci.h"
@@ -190,14 +192,20 @@ static void pc_init1(MachineState *machine,
gsi_state = pc_gsi_create(&x86ms->gsi, pcmc->pci_enabled);
if (pcmc->pci_enabled) {
+ PIIX3State *piix3;
+
pci_bus = i440fx_init(host_type,
pci_type,
- &i440fx_state, &piix3_devfn, &isa_bus, x86ms->gsi,
+ &i440fx_state,
system_memory, system_io, machine->ram_size,
x86ms->below_4g_mem_size,
x86ms->above_4g_mem_size,
pci_memory, ram_memory);
pcms->bus = pci_bus;
+
+ piix3 = piix3_create(pci_bus, &isa_bus);
+ piix3->pic = x86ms->gsi;
+ piix3_devfn = piix3->dev.devfn;
} else {
pci_bus = NULL;
i440fx_state = NULL;
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 95f23a263cc..82ece6b9e73 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -14,6 +14,7 @@
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/i386/pc.h"
+#include "hw/southbridge/piix.h"
#include "hw/irq.h"
#include "hw/hw.h"
#include "hw/i386/apic-msidef.h"
@@ -156,8 +157,8 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
v = 0;
}
v &= 0xf;
- if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
- xen_set_pci_link_route(xen_domid, address + i - 0x60, v);
+ if (((address + i) >= PIIX_PIRQCA) && ((address + i) <= PIIX_PIRQCD)) {
+ xen_set_pci_link_route(xen_domid, address + i - PIIX_PIRQCA, v);
}
}
}
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index aafd8e0e338..375cb6abe91 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -31,7 +31,6 @@
#include "sysemu/kvm.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
-#include "migration/qemu-file-types.h"
#include "migration/vmstate.h"
static int apic_irq_delivered;
@@ -262,52 +261,6 @@ static void apic_reset_common(DeviceState *dev)
apic_init_reset(dev);
}
-/* This function is only used for old state version 1 and 2 */
-static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
-{
- APICCommonState *s = opaque;
- APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
- int i;
-
- if (version_id > 2) {
- return -EINVAL;
- }
-
- /* XXX: what if the base changes? (registered memory regions) */
- qemu_get_be32s(f, &s->apicbase);
- qemu_get_8s(f, &s->id);
- qemu_get_8s(f, &s->arb_id);
- qemu_get_8s(f, &s->tpr);
- qemu_get_be32s(f, &s->spurious_vec);
- qemu_get_8s(f, &s->log_dest);
- qemu_get_8s(f, &s->dest_mode);
- for (i = 0; i < 8; i++) {
- qemu_get_be32s(f, &s->isr[i]);
- qemu_get_be32s(f, &s->tmr[i]);
- qemu_get_be32s(f, &s->irr[i]);
- }
- for (i = 0; i < APIC_LVT_NB; i++) {
- qemu_get_be32s(f, &s->lvt[i]);
- }
- qemu_get_be32s(f, &s->esr);
- qemu_get_be32s(f, &s->icr[0]);
- qemu_get_be32s(f, &s->icr[1]);
- qemu_get_be32s(f, &s->divide_conf);
- s->count_shift = qemu_get_be32(f);
- qemu_get_be32s(f, &s->initial_count);
- s->initial_count_load_time = qemu_get_be64(f);
- s->next_time = qemu_get_be64(f);
-
- if (version_id >= 2) {
- s->timer_expiry = qemu_get_be64(f);
- }
-
- if (info->post_load) {
- info->post_load(s);
- }
- return 0;
-}
-
static const VMStateDescription vmstate_apic_common;
static void apic_common_realize(DeviceState *dev, Error **errp)
@@ -408,8 +361,6 @@ static const VMStateDescription vmstate_apic_common = {
.name = "apic",
.version_id = 3,
.minimum_version_id = 3,
- .minimum_version_id_old = 1,
- .load_state_old = apic_load_old,
.pre_load = apic_pre_load,
.pre_save = apic_dispatch_pre_save,
.post_load = apic_dispatch_post_load,
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
index 98a289957ec..8a38813cc13 100644
--- a/hw/isa/Kconfig
+++ b/hw/isa/Kconfig
@@ -29,6 +29,10 @@ config PC87312
select FDC
select IDE_ISA
+config PIIX3
+ bool
+ select ISA_BUS
+
config PIIX4
bool
# For historical reasons, SuperIO devices are created in the board
diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs
index ff974855045..8e73960a750 100644
--- a/hw/isa/Makefile.objs
+++ b/hw/isa/Makefile.objs
@@ -3,6 +3,7 @@ common-obj-$(CONFIG_ISA_SUPERIO) += isa-superio.o
common-obj-$(CONFIG_APM) += apm.o
common-obj-$(CONFIG_I82378) += i82378.o
common-obj-$(CONFIG_PC87312) += pc87312.o
+common-obj-$(CONFIG_PIIX3) += piix3.o
common-obj-$(CONFIG_PIIX4) += piix4.o
common-obj-$(CONFIG_VT82C686) += vt82c686.o
common-obj-$(CONFIG_SMC37C669) += smc37c669-superio.o
diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
new file mode 100644
index 00000000000..fd1c78879f2
--- /dev/null
+++ b/hw/isa/piix3.c
@@ -0,0 +1,399 @@
+/*
+ * QEMU PIIX PCI ISA 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 "qemu/osdep.h"
+#include "qemu/range.h"
+#include "hw/southbridge/piix.h"
+#include "hw/irq.h"
+#include "hw/isa/isa.h"
+#include "hw/xen/xen.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "migration/vmstate.h"
+
+#define XEN_PIIX_NUM_PIRQS 128ULL
+
+#define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
+#define PIIX3_PCI_DEVICE(obj) \
+ OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE)
+
+#define TYPE_PIIX3_DEVICE "PIIX3"
+#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen"
+
+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_internal(PIIX3State *piix3, int pirq, int level)
+{
+ int pic_irq;
+ uint64_t mask;
+
+ pic_irq = piix3->dev.config[PIIX_PIRQCA + 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;
+}
+
+static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
+{
+ int pic_irq;
+
+ pic_irq = piix3->dev.config[PIIX_PIRQCA + pirq];
+ if (pic_irq >= PIIX_NUM_PIC_IRQS) {
+ return;
+ }
+
+ piix3_set_irq_level_internal(piix3, pirq, 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_PIRQCA + 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)
+{
+ PCIBus *bus = pci_get_bus(&piix3->dev);
+ 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(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_PIRQCA, 4)) {
+ PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
+ int pic_irq;
+
+ pci_bus_fire_intx_routing_notifier(pci_get_bus(&piix3->dev));
+ 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;
+ int pirq;
+
+ /*
+ * Because the i8259 has not been deserialized yet, qemu_irq_raise
+ * might bring the system to a different state than the saved one;
+ * for example, the interrupt could be masked but the i8259 would
+ * not know that yet and would trigger an interrupt in the CPU.
+ *
+ * Here, we update irq levels without raising the interrupt.
+ * Interrupt state will be deserialized separately through the i8259.
+ */
+ piix3->pic_levels = 0;
+ for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
+ piix3_set_irq_level_internal(piix3, pirq,
+ pci_bus_get_irq_level(pci_get_bus(&piix3->dev), pirq));
+ }
+ return 0;
+}
+
+static int 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(pci_get_bus(&piix3->dev), i);
+ }
+
+ return 0;
+}
+
+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,
+ .needed = piix3_rcr_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(rcr, PIIX3State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_piix3 = {
+ .name = "PIIX3",
+ .version_id = 3,
+ .minimum_version_id = 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 = (const VMStateDescription*[]) {
+ &vmstate_piix3_rcr,
+ NULL
+ }
+};
+
+
+static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
+{
+ PIIX3State *d = opaque;
+
+ if (val & 4) {
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ 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 void piix3_realize(PCIDevice *dev, Error **errp)
+{
+ PIIX3State *d = PIIX3_PCI_DEVICE(dev);
+
+ if (!isa_bus_new(DEVICE(d), get_system_memory(),
+ pci_address_space_io(dev), errp)) {
+ return;
+ }
+
+ memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
+ "piix3-reset-control", 1);
+ memory_region_add_subregion_overlap(pci_address_space_io(dev),
+ PIIX_RCR_IOPORT, &d->rcr_mem, 1);
+
+ qemu_register_reset(piix3_reset, d);
+}
+
+static void pci_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->hotpluggable = false;
+ k->realize = piix3_realize;
+ 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;
+ /*
+ * Reason: part of PIIX3 southbridge, needs to be wired up by
+ * pc_piix.c's pc_init1()
+ */
+ dc->user_creatable = false;
+}
+
+static const TypeInfo piix3_pci_type_info = {
+ .name = TYPE_PIIX3_PCI_DEVICE,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX3State),
+ .abstract = true,
+ .class_init = pci_piix3_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+ },
+};
+
+static void piix3_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->config_write = piix3_write_config;
+}
+
+static const TypeInfo piix3_info = {
+ .name = TYPE_PIIX3_DEVICE,
+ .parent = TYPE_PIIX3_PCI_DEVICE,
+ .class_init = piix3_class_init,
+};
+
+static void piix3_xen_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->config_write = piix3_write_config_xen;
+};
+
+static const TypeInfo piix3_xen_info = {
+ .name = TYPE_PIIX3_XEN_DEVICE,
+ .parent = TYPE_PIIX3_PCI_DEVICE,
+ .class_init = piix3_xen_class_init,
+};
+
+static void piix3_register_types(void)
+{
+ type_register_static(&piix3_pci_type_info);
+ type_register_static(&piix3_info);
+ type_register_static(&piix3_xen_info);
+}
+
+type_init(piix3_register_types)
+
+/*
+ * 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;
+}
+
+PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus)
+{
+ PIIX3State *piix3;
+ PCIDevice *pci_dev;
+
+ /*
+ * 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()) {
+ pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
+ TYPE_PIIX3_XEN_DEVICE);
+ piix3 = PIIX3_PCI_DEVICE(pci_dev);
+ pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+ piix3, XEN_PIIX_NUM_PIRQS);
+ } else {
+ pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
+ TYPE_PIIX3_DEVICE);
+ piix3 = PIIX3_PCI_DEVICE(pci_dev);
+ pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq,
+ piix3, PIIX_NUM_PIRQS);
+ pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq);
+ }
+ *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
+
+ return piix3;
+}
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index 890d999abf9..86678e68295 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -2,6 +2,7 @@
* QEMU PIIX4 PCI Bridge Emulation
*
* Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2018 Hervé Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,19 +24,34 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
#include "hw/i386/pc.h"
+#include "hw/southbridge/piix.h"
#include "hw/pci/pci.h"
#include "hw/isa/isa.h"
#include "hw/sysbus.h"
+#include "hw/dma/i8257.h"
+#include "hw/timer/i8254.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "hw/ide.h"
#include "migration/vmstate.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
PCIDevice *piix4_dev;
typedef struct PIIX4State {
PCIDevice dev;
+ qemu_irq cpu_intr;
+ qemu_irq *isa;
+
+ RTCState rtc;
+ /* Reset Control Register */
+ MemoryRegion rcr_mem;
+ uint8_t rcr;
} PIIX4State;
-#define TYPE_PIIX4_PCI_DEVICE "PIIX4"
#define PIIX4_PCI_DEVICE(obj) \
OBJECT_CHECK(PIIX4State, (obj), TYPE_PIIX4_PCI_DEVICE)
@@ -87,24 +103,102 @@ static const VMStateDescription vmstate_piix4 = {
}
};
+static void piix4_request_i8259_irq(void *opaque, int irq, int level)
+{
+ PIIX4State *s = opaque;
+ qemu_set_irq(s->cpu_intr, level);
+}
+
+static void piix4_set_i8259_irq(void *opaque, int irq, int level)
+{
+ PIIX4State *s = opaque;
+ qemu_set_irq(s->isa[irq], level);
+}
+
+static void piix4_rcr_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int len)
+{
+ PIIX4State *s = opaque;
+
+ if (val & 4) {
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ return;
+ }
+
+ s->rcr = val & 2; /* keep System Reset type only */
+}
+
+static uint64_t piix4_rcr_read(void *opaque, hwaddr addr, unsigned int len)
+{
+ PIIX4State *s = opaque;
+
+ return s->rcr;
+}
+
+static const MemoryRegionOps piix4_rcr_ops = {
+ .read = piix4_rcr_read,
+ .write = piix4_rcr_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
static void piix4_realize(PCIDevice *dev, Error **errp)
{
- PIIX4State *d = PIIX4_PCI_DEVICE(dev);
+ PIIX4State *s = PIIX4_PCI_DEVICE(dev);
+ ISABus *isa_bus;
+ qemu_irq *i8259_out_irq;
+ Error *err = NULL;
- if (!isa_bus_new(DEVICE(d), pci_address_space(dev),
- pci_address_space_io(dev), errp)) {
+ isa_bus = isa_bus_new(DEVICE(dev), pci_address_space(dev),
+ pci_address_space_io(dev), errp);
+ if (!isa_bus) {
return;
}
- piix4_dev = &d->dev;
+
+ qdev_init_gpio_in_named(DEVICE(dev), piix4_set_i8259_irq,
+ "isa", ISA_NUM_IRQS);
+ qdev_init_gpio_out_named(DEVICE(dev), &s->cpu_intr,
+ "intr", 1);
+
+ memory_region_init_io(&s->rcr_mem, OBJECT(dev), &piix4_rcr_ops, s,
+ "reset-control", 1);
+ memory_region_add_subregion_overlap(pci_address_space_io(dev),
+ PIIX_RCR_IOPORT, &s->rcr_mem, 1);
+
+ /* initialize i8259 pic */
+ i8259_out_irq = qemu_allocate_irqs(piix4_request_i8259_irq, s, 1);
+ s->isa = i8259_init(isa_bus, *i8259_out_irq);
+
+ /* initialize ISA irqs */
+ isa_bus_irqs(isa_bus, s->isa);
+
+ /* initialize pit */
+ i8254_pit_init(isa_bus, 0x40, 0, NULL);
+
+ /* DMA */
+ i8257_dma_init(isa_bus, 0);
+
+ /* RTC */
+ qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus));
+ qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ isa_init_irq(ISA_DEVICE(&s->rtc), &s->rtc.irq, RTC_ISA_IRQ);
+
+ piix4_dev = dev;
}
-int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
+static void piix4_init(Object *obj)
{
- PCIDevice *d;
+ PIIX4State *s = PIIX4_PCI_DEVICE(obj);
- d = pci_create_simple_multifunction(bus, devfn, true, "PIIX4");
- *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(d), "isa.0"));
- return d->devfn;
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_MC146818_RTC);
}
static void piix4_class_init(ObjectClass *klass, void *data)
@@ -131,6 +225,7 @@ static const TypeInfo piix4_info = {
.name = TYPE_PIIX4_PCI_DEVICE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PIIX4State),
+ .instance_init = piix4_init,
.class_init = piix4_class_init,
.interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
@@ -144,3 +239,31 @@ static void piix4_register_types(void)
}
type_init(piix4_register_types)
+
+DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus,
+ I2CBus **smbus, size_t ide_buses)
+{
+ size_t ide_drives = ide_buses * MAX_IDE_DEVS;
+ DriveInfo **hd;
+ PCIDevice *pci;
+ DeviceState *dev;
+
+ pci = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(10, 0),
+ true, TYPE_PIIX4_PCI_DEVICE);
+ dev = DEVICE(pci);
+ if (isa_bus) {
+ *isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
+ }
+
+ hd = g_new(DriveInfo *, ide_drives);
+ ide_drive_get(hd, ide_drives);
+ pci_piix4_ide_init(pci_bus, hd, pci->devfn + 1);
+ g_free(hd);
+ pci_create_simple(pci_bus, pci->devfn + 2, "piix4-usb-uhci");
+ if (smbus) {
+ *smbus = piix4_pm_init(pci_bus, pci->devfn + 3, 0x1100,
+ isa_get_irq(NULL, 9), NULL, 0, NULL);
+ }
+
+ return dev;
+}
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index f325bd6c1c9..5cab9c1ee17 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -28,6 +28,7 @@
#include "hw/mips/mips.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
+#include "hw/southbridge/piix.h"
#include "migration/vmstate.h"
#include "hw/i386/pc.h"
#include "hw/irq.h"
@@ -1012,12 +1013,12 @@ static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
- pic_irq = piix4_dev->config[0x60 + irq_num];
+ pic_irq = piix4_dev->config[PIIX_PIRQCA + 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]) {
+ if (pic_irq == piix4_dev->config[PIIX_PIRQCA + i]) {
pic_level |= pci_irq_levels[i];
}
}
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index c1c8810e719..92e9ca5bfa5 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -26,9 +26,8 @@
#include "qemu/units.h"
#include "qemu-common.h"
#include "cpu.h"
-#include "hw/i386/pc.h"
+#include "hw/southbridge/piix.h"
#include "hw/isa/superio.h"
-#include "hw/dma/i8257.h"
#include "hw/char/serial.h"
#include "net/net.h"
#include "hw/boards.h"
@@ -45,8 +44,6 @@
#include "hw/irq.h"
#include "hw/loader.h"
#include "elf.h"
-#include "hw/rtc/mc146818rtc.h"
-#include "hw/timer/i8254.h"
#include "exec/address-spaces.h"
#include "hw/sysbus.h" /* SysBusDevice */
#include "qemu/host-utils.h"
@@ -97,11 +94,9 @@ typedef struct {
SysBusDevice parent_obj;
MIPSCPSState cps;
- qemu_irq *i8259;
+ qemu_irq i8259[ISA_NUM_IRQS];
} MaltaState;
-static ISADevice *pit;
-
static struct _loaderparams {
int ram_size, ram_low_size;
const char *kernel_filename;
@@ -1235,12 +1230,9 @@ void mips_malta_init(MachineState *machine)
int64_t kernel_entry, bootloader_run_addr;
PCIBus *pci_bus;
ISABus *isa_bus;
- qemu_irq *isa_irq;
qemu_irq cbus_irq, i8259_irq;
- int piix4_devfn;
I2CBus *smbus;
DriveInfo *dinfo;
- DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
int fl_idx = 0;
int be;
@@ -1407,37 +1399,17 @@ void mips_malta_init(MachineState *machine)
/* Board ID = 0x420 (Malta Board with CoreLV) */
stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
- /*
- * We have a circular dependency problem: pci_bus depends on isa_irq,
- * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
- * on piix4, and piix4 depends on pci_bus. To stop the cycle we have
- * qemu_irq_proxy() adds an extra bit of indirection, allowing us
- * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
- */
- isa_irq = qemu_irq_proxy(&s->i8259, 16);
-
/* Northbridge */
- pci_bus = gt64120_register(isa_irq);
+ pci_bus = gt64120_register(s->i8259);
/* Southbridge */
- ide_drive_get(hd, ARRAY_SIZE(hd));
+ dev = piix4_create(pci_bus, &isa_bus, &smbus, MAX_IDE_BUS);
- piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
-
- /*
- * Interrupt controller
- * The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2
- */
- s->i8259 = i8259_init(isa_bus, i8259_irq);
-
- isa_bus_irqs(isa_bus, s->i8259);
- pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
- pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
- smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
- isa_get_irq(NULL, 9), NULL, 0, NULL);
- pit = i8254_pit_init(isa_bus, 0x40, 0, NULL);
- i8257_dma_init(isa_bus, 0);
- mc146818_rtc_init(isa_bus, 2000, NULL);
+ /* Interrupt controller */
+ qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq);
+ for (int i = 0; i < ISA_NUM_IRQS; i++) {
+ s->i8259[i] = qdev_get_gpio_in_named(dev, "isa", i);
+ }
/* generate SPD EEPROM data */
generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
index 1edc1a31d41..b0aa8351c4a 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -28,11 +28,10 @@ config PCI_SABRE
select PCI
bool
-config PCI_PIIX
+config PCI_I440FX
bool
select PCI
select PAM
- select ISA_BUS
config PCI_EXPRESS_Q35
bool
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index a9cd3e022d5..efd752b7662 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -13,7 +13,7 @@ common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
common-obj-$(CONFIG_PCI_SABRE) += sabre.o
common-obj-$(CONFIG_FULONG) += bonito.o
-common-obj-$(CONFIG_PCI_PIIX) += piix.o
+common-obj-$(CONFIG_PCI_I440FX) += i440fx.o
common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o
common-obj-$(CONFIG_PCI_EXPRESS_GENERIC_BRIDGE) += gpex.o
common-obj-$(CONFIG_PCI_EXPRESS_XILINX) += xilinx-pcie.o
diff --git a/hw/pci-host/piix.c b/hw/pci-host/i440fx.c
index 135c6455350..f27131102db 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/i440fx.c
@@ -24,21 +24,14 @@
#include "qemu/osdep.h"
#include "hw/i386/pc.h"
-#include "hw/irq.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
+#include "hw/pci-host/i440fx.h"
#include "hw/qdev-properties.h"
-#include "hw/isa/isa.h"
#include "hw/sysbus.h"
#include "qapi/error.h"
-#include "qemu/range.h"
-#include "hw/xen/xen.h"
-#include "migration/qemu-file-types.h"
#include "migration/vmstate.h"
#include "hw/pci-host/pam.h"
-#include "sysemu/reset.h"
-#include "sysemu/runstate.h"
-#include "hw/i386/ioapic.h"
#include "qapi/visitor.h"
#include "qemu/error-report.h"
@@ -58,50 +51,9 @@ typedef struct I440FXState {
uint32_t short_root_bus;
} 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
-
-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_PIIX3_PCI_DEVICE "pci-piix3"
-#define PIIX3_PCI_DEVICE(obj) \
- OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE)
-
#define I440FX_PCI_DEVICE(obj) \
OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
-#define TYPE_PIIX3_DEVICE "PIIX3"
-#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen"
-
struct PCII440FXState {
/*< private >*/
PCIDevice parent_obj;
@@ -128,21 +80,6 @@ struct PCII440FXState {
*/
#define I440FX_COREBOOT_RAM_SIZE 0x57
-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;
@@ -174,28 +111,6 @@ static void i440fx_write_config(PCIDevice *dev,
}
}
-static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
-{
- PCII440FXState *d = opaque;
- PCIDevice *pd = PCI_DEVICE(d);
- int ret, i;
- uint8_t smm_enabled;
-
- ret = pci_device_load(pd, f);
- if (ret < 0)
- return ret;
- i440fx_update_memory_mappings(d);
- qemu_get_8s(f, &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;
@@ -208,8 +123,6 @@ 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(parent_obj, PCII440FXState),
@@ -358,8 +271,6 @@ static void i440fx_realize(PCIDevice *dev, Error **errp)
PCIBus *i440fx_init(const char *host_type, const char *pci_type,
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,
@@ -372,7 +283,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
PCIBus *b;
PCIDevice *d;
PCIHostState *s;
- PIIX3State *piix3;
PCII440FXState *f;
unsigned i;
I440FXState *i440fx;
@@ -425,29 +335,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
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()) {
- PCIDevice *pci_dev = pci_create_simple_multifunction(b,
- -1, true, TYPE_PIIX3_XEN_DEVICE);
- piix3 = PIIX3_PCI_DEVICE(pci_dev);
- pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq,
- piix3, XEN_PIIX_NUM_PIRQS);
- } else {
- PCIDevice *pci_dev = pci_create_simple_multifunction(b,
- -1, true, TYPE_PIIX3_DEVICE);
- piix3 = PIIX3_PCI_DEVICE(pci_dev);
- 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;
@@ -467,312 +354,6 @@ PCIBus *find_i440fx(void)
return s ? s->bus : NULL;
}
-/* 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_internal(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;
-}
-
-static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
-{
- int pic_irq;
-
- pic_irq = piix3->dev.config[PIIX_PIRQC + pirq];
- if (pic_irq >= PIIX_NUM_PIC_IRQS) {
- return;
- }
-
- piix3_set_irq_level_internal(piix3, pirq, 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)
-{
- PCIBus *bus = pci_get_bus(&piix3->dev);
- 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(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 = PIIX3_PCI_DEVICE(dev);
- int pic_irq;
-
- pci_bus_fire_intx_routing_notifier(pci_get_bus(&piix3->dev));
- 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;
- int pirq;
-
- /* Because the i8259 has not been deserialized yet, qemu_irq_raise
- * might bring the system to a different state than the saved one;
- * for example, the interrupt could be masked but the i8259 would
- * not know that yet and would trigger an interrupt in the CPU.
- *
- * Here, we update irq levels without raising the interrupt.
- * Interrupt state will be deserialized separately through the i8259.
- */
- piix3->pic_levels = 0;
- for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
- piix3_set_irq_level_internal(piix3, pirq,
- pci_bus_get_irq_level(pci_get_bus(&piix3->dev), pirq));
- }
- return 0;
-}
-
-static int 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(pci_get_bus(&piix3->dev), i);
- }
-
- return 0;
-}
-
-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,
- .needed = piix3_rcr_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(rcr, PIIX3State),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_piix3 = {
- .name = "PIIX3",
- .version_id = 3,
- .minimum_version_id = 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 = (const VMStateDescription*[]) {
- &vmstate_piix3_rcr,
- NULL
- }
-};
-
-
-static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
-{
- PIIX3State *d = opaque;
-
- if (val & 4) {
- qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
- 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 void piix3_realize(PCIDevice *dev, Error **errp)
-{
- PIIX3State *d = PIIX3_PCI_DEVICE(dev);
-
- if (!isa_bus_new(DEVICE(d), get_system_memory(),
- pci_address_space_io(dev), errp)) {
- return;
- }
-
- memory_region_init_io(&d->rcr_mem, OBJECT(dev), &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);
-}
-
-static void pci_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->hotpluggable = false;
- k->realize = piix3_realize;
- 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;
- /*
- * Reason: part of PIIX3 southbridge, needs to be wired up by
- * pc_piix.c's pc_init1()
- */
- dc->user_creatable = false;
-}
-
-static const TypeInfo piix3_pci_type_info = {
- .name = TYPE_PIIX3_PCI_DEVICE,
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PIIX3State),
- .abstract = true,
- .class_init = pci_piix3_class_init,
- .interfaces = (InterfaceInfo[]) {
- { INTERFACE_CONVENTIONAL_PCI_DEVICE },
- { },
- },
-};
-
-static void piix3_class_init(ObjectClass *klass, void *data)
-{
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->config_write = piix3_write_config;
-}
-
-static const TypeInfo piix3_info = {
- .name = TYPE_PIIX3_DEVICE,
- .parent = TYPE_PIIX3_PCI_DEVICE,
- .class_init = piix3_class_init,
-};
-
-static void piix3_xen_class_init(ObjectClass *klass, void *data)
-{
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->config_write = piix3_write_config_xen;
-};
-
-static const TypeInfo piix3_xen_info = {
- .name = TYPE_PIIX3_XEN_DEVICE,
- .parent = TYPE_PIIX3_PCI_DEVICE,
- .class_init = piix3_xen_class_init,
-};
-
static void i440fx_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -934,9 +515,6 @@ static void i440fx_register_types(void)
{
type_register_static(&i440fx_info);
type_register_static(&igd_passthrough_i440fx_info);
- type_register_static(&piix3_pci_type_info);
- type_register_static(&piix3_info);
- type_register_static(&piix3_xen_info);
type_register_static(&i440fx_pcihost_info);
}
diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c
index 57bf10cc942..050875b4973 100644
--- a/hw/timer/i8254_common.c
+++ b/hw/timer/i8254_common.c
@@ -29,7 +29,6 @@
#include "qemu/timer.h"
#include "hw/timer/i8254.h"
#include "hw/timer/i8254_internal.h"
-#include "migration/qemu-file-types.h"
#include "migration/vmstate.h"
/* val must be 0 or 1 */
@@ -202,43 +201,6 @@ static const VMStateDescription vmstate_pit_channel = {
}
};
-static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
-{
- PITCommonState *pit = opaque;
- PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
- PITChannelState *s;
- int i;
-
- if (version_id != 1) {
- return -EINVAL;
- }
-
- for (i = 0; i < 3; i++) {
- s = &pit->channels[i];
- s->count = qemu_get_be32(f);
- qemu_get_be16s(f, &s->latched_count);
- qemu_get_8s(f, &s->count_latched);
- qemu_get_8s(f, &s->status_latched);
- qemu_get_8s(f, &s->status);
- qemu_get_8s(f, &s->read_state);
- qemu_get_8s(f, &s->write_state);
- qemu_get_8s(f, &s->write_latch);
- qemu_get_8s(f, &s->rw_mode);
- qemu_get_8s(f, &s->mode);
- qemu_get_8s(f, &s->bcd);
- qemu_get_8s(f, &s->gate);
- s->count_load_time = qemu_get_be64(f);
- s->irq_disabled = 0;
- if (i == 0) {
- s->next_transition_time = qemu_get_be64(f);
- }
- }
- if (c->post_load) {
- c->post_load(pit);
- }
- return 0;
-}
-
static int pit_dispatch_pre_save(void *opaque)
{
PITCommonState *s = opaque;
@@ -266,8 +228,6 @@ static const VMStateDescription vmstate_pit_common = {
.name = "i8254",
.version_id = 3,
.minimum_version_id = 2,
- .minimum_version_id_old = 1,
- .load_state_old = pit_load_old,
.pre_save = pit_dispatch_pre_save,
.post_load = pit_dispatch_post_load,
.fields = (VMStateField[]) {
diff --git a/include/hw/acpi/piix4.h b/include/hw/acpi/piix4.h
deleted file mode 100644
index 028bb53e3df..00000000000
--- a/include/hw/acpi/piix4.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef HW_ACPI_PIIX4_H
-#define HW_ACPI_PIIX4_H
-
-#define TYPE_PIIX4_PM "PIIX4_PM"
-
-#endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index f040a720959..e6fa8418ca6 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -228,46 +228,9 @@ int cmos_get_fd_drive_type(FloppyDriveType fd0);
#define PORT92_A20_LINE "a20"
-/* acpi_piix.c */
-
-I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- qemu_irq sci_irq, qemu_irq smi_irq,
- int smm_enabled, DeviceState **piix4_pm);
-
/* hpet.c */
extern int no_hpet;
-/* piix_pci.c */
-struct PCII440FXState;
-typedef struct PCII440FXState PCII440FXState;
-
-#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
-#define TYPE_I440FX_PCI_DEVICE "i440FX"
-
-#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
-
-/*
- * 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
-
-PCIBus *i440fx_init(const char *host_type, const char *pci_type,
- PCII440FXState **pi440fx_state, int *piix_devfn,
- ISABus **isa_bus, qemu_irq *pic,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
- ram_addr_t ram_size,
- ram_addr_t below_4g_mem_size,
- ram_addr_t above_4g_mem_size,
- MemoryRegion *pci_memory,
- MemoryRegion *ram_memory);
-
-PCIBus *find_i440fx(void);
-/* piix4.c */
-extern PCIDevice *piix4_dev;
-int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn);
-
/* pc_sysfw.c */
void pc_system_flash_create(PCMachineState *pcms);
void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);
diff --git a/include/hw/irq.h b/include/hw/irq.h
index fe527f6f51d..24ba0ece116 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -51,11 +51,6 @@ qemu_irq qemu_irq_invert(qemu_irq irq);
*/
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
-/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
- * may be set later.
- */
-qemu_irq *qemu_irq_proxy(qemu_irq **target, int n);
-
/* For internal use in qtest. Similar to qemu_irq_split, but operating
on an existing vector of qemu_irq. */
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index 018ada4f6f6..79f703fd6c1 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -147,4 +147,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d)
return ISA_BUS(qdev_get_parent_bus(DEVICE(d)));
}
+#define TYPE_PIIX4_PCI_DEVICE "piix4-isa"
+
#endif
diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h
new file mode 100644
index 00000000000..f54e6466e49
--- /dev/null
+++ b/include/hw/pci-host/i440fx.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU i440FX North Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_PCI_I440FX_H
+#define HW_PCI_I440FX_H
+
+#include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
+
+typedef struct PCII440FXState PCII440FXState;
+
+#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+
+#define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX"
+
+PCIBus *i440fx_init(const char *host_type, const char *pci_type,
+ PCII440FXState **pi440fx_state,
+ MemoryRegion *address_space_mem,
+ MemoryRegion *address_space_io,
+ ram_addr_t ram_size,
+ ram_addr_t below_4g_mem_size,
+ ram_addr_t above_4g_mem_size,
+ MemoryRegion *pci_memory,
+ MemoryRegion *ram_memory);
+
+PCIBus *find_i440fx(void);
+
+#endif
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
new file mode 100644
index 00000000000..152628c6d9f
--- /dev/null
+++ b/include/hw/southbridge/piix.h
@@ -0,0 +1,74 @@
+/*
+ * QEMU PIIX South Bridge Emulation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2018 Hervé Poussineau
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_SOUTHBRIDGE_PIIX_H
+#define HW_SOUTHBRIDGE_PIIX_H
+
+#include "hw/pci/pci.h"
+
+#define TYPE_PIIX4_PM "PIIX4_PM"
+
+I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+ qemu_irq sci_irq, qemu_irq smi_irq,
+ int smm_enabled, DeviceState **piix4_pm);
+
+/* PIRQRC[A:D]: PIRQx Route Control Registers */
+#define PIIX_PIRQCA 0x60
+#define PIIX_PIRQCB 0x61
+#define PIIX_PIRQCC 0x62
+#define PIIX_PIRQCD 0x63
+
+/*
+ * Reset Control Register: PCI-accessible ISA-Compatible Register at address
+ * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
+ */
+#define PIIX_RCR_IOPORT 0xcf9
+
+#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
+#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */
+
+typedef struct PIIXState {
+ 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 (PIIX_RCR_IOPORT) */
+ MemoryRegion rcr_mem;
+} PIIX3State;
+
+extern PCIDevice *piix4_dev;
+
+PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus);
+
+DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus,
+ I2CBus **smbus, size_t ide_buses);
+
+#endif
diff --git a/stubs/pci-host-piix.c b/stubs/pci-host-piix.c
index 6ed81b1f21c..93975adbfeb 100644
--- a/stubs/pci-host-piix.c
+++ b/stubs/pci-host-piix.c
@@ -1,5 +1,6 @@
#include "qemu/osdep.h"
-#include "hw/i386/pc.h"
+#include "hw/pci-host/i440fx.h"
+
PCIBus *find_i440fx(void)
{
return NULL;