@@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qemu/range.h"
+#include "qapi/error.h"
#include "hw/southbridge/piix.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
@@ -277,7 +278,7 @@ static const MemoryRegionOps rcr_ops = {
.endianness = DEVICE_LITTLE_ENDIAN
};
-static void piix3_realize(PCIDevice *dev, Error **errp)
+static void pci_piix3_realize(PCIDevice *dev, Error **errp)
{
PIIX3State *d = PIIX3_PCI_DEVICE(dev);
@@ -302,7 +303,6 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data)
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;
@@ -326,11 +326,28 @@ static const TypeInfo piix3_pci_type_info = {
},
};
+static void piix3_realize(PCIDevice *dev, Error **errp)
+{
+ ERRP_GUARD();
+ PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
+ PCIBus *pci_bus = pci_get_bus(dev);
+
+ pci_piix3_realize(dev, errp);
+ if (*errp) {
+ return;
+ }
+
+ 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);
+};
+
static void piix3_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->config_write = piix3_write_config;
+ k->realize = piix3_realize;
}
static const TypeInfo piix3_info = {
@@ -339,11 +356,33 @@ static const TypeInfo piix3_info = {
.class_init = piix3_class_init,
};
+static void piix3_xen_realize(PCIDevice *dev, Error **errp)
+{
+ ERRP_GUARD();
+ PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
+ PCIBus *pci_bus = pci_get_bus(dev);
+
+ pci_piix3_realize(dev, errp);
+ if (*errp) {
+ return;
+ }
+
+ /*
+ * 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.
+ */
+ pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq,
+ piix3, XEN_PIIX_NUM_PIRQS);
+};
+
static void piix3_xen_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->config_write = piix3_write_config_xen;
+ k->realize = piix3_xen_realize;
};
static const TypeInfo piix3_xen_info = {
@@ -365,27 +404,11 @@ PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus)
{
PIIX3State *piix3;
PCIDevice *pci_dev;
+ const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE
+ : TYPE_PIIX3_DEVICE;
- /*
- * 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);
- }
+ pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type);
+ piix3 = PIIX3_PCI_DEVICE(pci_dev);
*isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
return piix3;
@@ -204,6 +204,8 @@ static const MemoryRegionOps piix4_rcr_ops = {
static void piix4_realize(PCIDevice *dev, Error **errp)
{
PIIX4State *s = PIIX4_PCI_DEVICE(dev);
+ PCIDevice *pci;
+ PCIBus *pci_bus = pci_get_bus(dev);
ISABus *isa_bus;
qemu_irq *i8259_out_irq;
@@ -242,6 +244,15 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
return;
}
s->rtc.irq = isa_get_irq(ISA_DEVICE(&s->rtc), s->rtc.isairq);
+
+ /* IDE */
+ pci = pci_create_simple(pci_bus, dev->devfn + 1, "piix4-ide");
+ pci_ide_create_devs(pci);
+
+ /* USB */
+ pci_create_simple(pci_bus, dev->devfn + 2, "piix4-usb-uhci");
+
+ pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS);
}
static void piix4_init(Object *obj)
@@ -292,7 +303,6 @@ type_init(piix4_register_types)
DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
{
- PIIX4State *s;
PCIDevice *pci;
DeviceState *dev;
int devfn = PCI_DEVFN(10, 0);
@@ -300,22 +310,16 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
pci = pci_create_simple_multifunction(pci_bus, devfn, true,
TYPE_PIIX4_PCI_DEVICE);
dev = DEVICE(pci);
- s = PIIX4_PCI_DEVICE(pci);
+
if (isa_bus) {
*isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
}
- pci = pci_create_simple(pci_bus, devfn + 1, "piix4-ide");
- pci_ide_create_devs(pci);
-
- pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci");
if (smbus) {
*smbus = piix4_pm_init(pci_bus, devfn + 3, 0x1100,
qdev_get_gpio_in_named(dev, "isa", 9),
NULL, 0, NULL);
}
- pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS);
-
return dev;
}