From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Move all the PIIX3 functions to a new file: hw/isa/piix3.c.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
Checkpatch warning:
ERROR: spaces required around that '*' (ctx:VxV)
#312: FILE: hw/isa/piix3.c:248:
+ .subsections = (const VMStateDescription*[]) {
^
---
MAINTAINERS | 1 +
hw/i386/Kconfig | 1 +
hw/isa/Kconfig | 4 +
hw/isa/Makefile.objs | 1 +
hw/isa/piix3.c | 399 +++++++++++++++++++++++++++++++++
hw/pci-host/Kconfig | 1 -
hw/pci-host/piix.c | 402 ----------------------------------
include/hw/southbridge/piix.h | 36 +++
8 files changed, 442 insertions(+), 403 deletions(-)
create mode 100644 hw/isa/piix3.c
diff --git a/MAINTAINERS b/MAINTAINERS
index adf059a164..4845f47d93 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1231,6 +1231,7 @@ 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/piix3.c
F: hw/isa/lpc_ich9.c
F: hw/i2c/smbus_ich9.c
F: hw/acpi/piix4.c
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index c5c9d4900e..589d75e26a 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -61,6 +61,7 @@ config I440FX
select PC_ACPI
select ACPI_SMBUS
select PCI_PIIX
+ select PIIX3
select IDE_PIIX
select DIMM
select SMBIOS
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
index 98a289957e..8a38813cc1 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 ff97485504..8e73960a75 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 0000000000..05146447ef
--- /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), 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/pci-host/Kconfig b/hw/pci-host/Kconfig
index 1edc1a31d4..397043b289 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -32,7 +32,6 @@ config PCI_PIIX
bool
select PCI
select PAM
- select ISA_BUS
config PCI_EXPRESS_Q35
bool
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 61f91ff561..79ecd58a2b 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -24,22 +24,15 @@
#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/southbridge/piix.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/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"
@@ -59,49 +52,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
-
-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,22 +81,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;
@@ -333,36 +270,6 @@ static void i440fx_realize(PCIDevice *dev, Error **errp)
}
}
-static 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;
-}
-
PCIBus *i440fx_init(const char *host_type, const char *pci_type,
PCII440FXState **pi440fx_state,
int *piix3_devfn,
@@ -455,312 +362,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_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), 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);
@@ -922,9 +523,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/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index 9c92c37a4d..324a3a99fc 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -12,6 +12,8 @@
#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,
@@ -30,8 +32,42 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
*/
#define 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 (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);
--
2.21.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
On Tuesday, October 15, 2019, Philippe Mathieu-Daudé <philmd@redhat.com>
wrote:
> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
>
> Move all the PIIX3 functions to a new file: hw/isa/piix3.c.
>
> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> ---
> Checkpatch warning:
>
> ERROR: spaces required around that '*' (ctx:VxV)
> #312: FILE: hw/isa/piix3.c:248:
> + .subsections = (const VMStateDescription*[]) {
> ^
> ---
> MAINTAINERS | 1 +
> hw/i386/Kconfig | 1 +
> hw/isa/Kconfig | 4 +
> hw/isa/Makefile.objs | 1 +
> hw/isa/piix3.c | 399 +++++++++++++++++++++++++++++++++
> hw/pci-host/Kconfig | 1 -
> hw/pci-host/piix.c | 402 ----------------------------------
> include/hw/southbridge/piix.h | 36 +++
> 8 files changed, 442 insertions(+), 403 deletions(-)
> create mode 100644 hw/isa/piix3.c
>
>
Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index adf059a164..4845f47d93 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1231,6 +1231,7 @@ 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/piix3.c
> F: hw/isa/lpc_ich9.c
> F: hw/i2c/smbus_ich9.c
> F: hw/acpi/piix4.c
> diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
> index c5c9d4900e..589d75e26a 100644
> --- a/hw/i386/Kconfig
> +++ b/hw/i386/Kconfig
> @@ -61,6 +61,7 @@ config I440FX
> select PC_ACPI
> select ACPI_SMBUS
> select PCI_PIIX
> + select PIIX3
> select IDE_PIIX
> select DIMM
> select SMBIOS
> diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
> index 98a289957e..8a38813cc1 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 ff97485504..8e73960a75 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 0000000000..05146447ef
> --- /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),
> 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/pci-host/Kconfig b/hw/pci-host/Kconfig
> index 1edc1a31d4..397043b289 100644
> --- a/hw/pci-host/Kconfig
> +++ b/hw/pci-host/Kconfig
> @@ -32,7 +32,6 @@ config PCI_PIIX
> bool
> select PCI
> select PAM
> - select ISA_BUS
>
> config PCI_EXPRESS_Q35
> bool
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index 61f91ff561..79ecd58a2b 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -24,22 +24,15 @@
>
> #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/southbridge/piix.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/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"
>
> @@ -59,49 +52,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
> -
> -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,22 +81,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;
> @@ -333,36 +270,6 @@ static void i440fx_realize(PCIDevice *dev, Error
> **errp)
> }
> }
>
> -static 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;
> -}
> -
> PCIBus *i440fx_init(const char *host_type, const char *pci_type,
> PCII440FXState **pi440fx_state,
> int *piix3_devfn,
> @@ -455,312 +362,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_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),
> 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);
> @@ -922,9 +523,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/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
> index 9c92c37a4d..324a3a99fc 100644
> --- a/include/hw/southbridge/piix.h
> +++ b/include/hw/southbridge/piix.h
> @@ -12,6 +12,8 @@
> #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,
> @@ -30,8 +32,42 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t
> smb_io_base,
> */
> #define 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 (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);
>
> --
> 2.21.0
>
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
© 2016 - 2026 Red Hat, Inc.