* THE SOFTWARE.
*/
-#include "hw.h"
-#include "pc.h"
-#include "pci.h"
-#include "pci_host.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "range.h"
-#include "xen.h"
-#include "pam.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "qemu/range.h"
+#include "hw/xen.h"
+#include "hw/pam.h"
+#include "sysemu/sysemu.h"
/*
* I440FX chipset data sheet.
#define XEN_PIIX_NUM_PIRQS 128ULL
#define PIIX_PIRQC 0x60
+/*
+ * Reset Control Register: PCI-accessible ISA-Compatible Register at address
+ * 0xcf9, provided by the PCI/ISA bridge (PIIX3 PCI function 0, 8086:7000).
+ */
+#define RCR_IOPORT 0xcf9
+
typedef struct PIIX3State {
PCIDevice dev;
/* This member isn't used. Just for save/load compatibility */
int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
+
+ /* Reset Control Register contents */
+ uint8_t rcr;
+
+ /* IO memory region for Reset Control Register (RCR_IOPORT) */
+ MemoryRegion rcr_mem;
} PIIX3State;
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+#define I440FX_PCI_DEVICE(obj) \
+ OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+
struct PCII440FXState {
PCIDevice dev;
MemoryRegion *system_memory;
static void i440fx_write_config(PCIDevice *dev,
uint32_t address, uint32_t val, int len)
{
- PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+ PCII440FXState *d = I440FX_PCI_DEVICE(dev);
/* XXX: implement SMRAM.D_LOCK */
pci_default_write_config(dev, address, val, len);
static int i440fx_initfn(PCIDevice *dev)
{
- PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+ PCII440FXState *d = I440FX_PCI_DEVICE(dev);
d->dev.config[I440FX_SMRAM] = 0x02;
dev = qdev_create(NULL, "i440FX-pcihost");
s = PCI_HOST_BRIDGE(dev);
- s->address_space = address_space_mem;
b = pci_bus_new(dev, NULL, pci_address_space,
- address_space_io, 0);
+ address_space_io, 0, TYPE_PCI_BUS);
s->bus = b;
object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
qdev_init_nofail(dev);
d = pci_create_simple(b, 0, device_name);
- *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
+ *pi440fx_state = I440FX_PCI_DEVICE(d);
f = *pi440fx_state;
f->system_memory = address_space_mem;
f->pci_address_space = pci_address_space;
pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
}
piix3->pic = pic;
- *isa_bus = DO_UPCAST(ISABus, qbus,
- qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
+ *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
*piix3_devfn = piix3->dev.devfn;
{
PCIBus *b;
- b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic,
+ b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
+ piix3_devfn, isa_bus, pic,
address_space_mem, address_space_io, ram_size,
pci_hole_start, pci_hole_size,
pci_hole64_start, pci_hole64_size,
PIIX3State *d = opaque;
uint8_t *pci_conf = d->dev.config;
- pci_conf[0x04] = 0x07; // master, memory and I/O
+ 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[0x07] = 0x02; /* PCI_status_devsel_medium */
pci_conf[0x4c] = 0x4d;
pci_conf[0x4e] = 0x03;
pci_conf[0x4f] = 0x00;
pci_conf[0xae] = 0x00;
d->pic_levels = 0;
+ d->rcr = 0;
}
static int piix3_post_load(void *opaque, int version_id)
}
}
+static bool piix3_rcr_needed(void *opaque)
+{
+ PIIX3State *piix3 = opaque;
+
+ return (piix3->rcr != 0);
+}
+
+static const VMStateDescription vmstate_piix3_rcr = {
+ .name = "PIIX3/rcr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT8(rcr, PIIX3State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_piix3 = {
.name = "PIIX3",
.version_id = 3,
.minimum_version_id_old = 2,
.post_load = piix3_post_load,
.pre_save = piix3_pre_save,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, PIIX3State),
VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection[]) {
+ {
+ .vmsd = &vmstate_piix3_rcr,
+ .needed = piix3_rcr_needed,
+ },
+ { 0 }
}
};
+
+static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
+{
+ PIIX3State *d = opaque;
+
+ if (val & 4) {
+ qemu_system_reset_request();
+ return;
+ }
+ d->rcr = val & 2; /* keep System Reset type only */
+}
+
+static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
+{
+ PIIX3State *d = opaque;
+
+ return d->rcr;
+}
+
+static const MemoryRegionOps rcr_ops = {
+ .read = rcr_read,
+ .write = rcr_write,
+ .endianness = DEVICE_LITTLE_ENDIAN
+};
+
static int piix3_initfn(PCIDevice *dev)
{
PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
- isa_bus_new(&d->dev.qdev, pci_address_space_io(dev));
+ isa_bus_new(DEVICE(d), pci_address_space_io(dev));
+
+ memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
+ memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
+ &d->rcr_mem, 1);
+
qemu_register_reset(piix3_reset, d);
return 0;
}
k->init = piix3_initfn;
k->config_write = piix3_write_config;
k->vendor_id = PCI_VENDOR_ID_INTEL;
- k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0;
k->class_id = PCI_CLASS_BRIDGE_ISA;
}
k->init = piix3_initfn;
k->config_write = piix3_write_config_xen;
k->vendor_id = PCI_VENDOR_ID_INTEL;
- k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0;
k->class_id = PCI_CLASS_BRIDGE_ISA;
};
}
static const TypeInfo i440fx_info = {
- .name = "i440FX",
+ .name = TYPE_I440FX_PCI_DEVICE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(PCII440FXState),
.class_init = i440fx_class_init,