#include "pci_host.h"
#include "isa.h"
#include "sysbus.h"
+#include "range.h"
+
+/*
+ * I440FX chipset data sheet.
+ * http://download.intel.com/design/chipsets/datashts/29054901.pdf
+ */
typedef PCIHostState I440FXState;
PIIX3State *piix3;
};
+
+#define I440FX_PAM 0x59
+#define I440FX_PAM_SIZE 7
+#define I440FX_SMRAM 0x72
+
static void piix3_set_irq(void *opaque, int irq_num, int level);
/* return the global irq number corresponding to a given device irq
int i, r;
uint32_t smram, addr;
- update_pam(d, 0xf0000, 0x100000, (d->dev.config[0x59] >> 4) & 3);
+ update_pam(d, 0xf0000, 0x100000, (d->dev.config[I440FX_PAM] >> 4) & 3);
for(i = 0; i < 12; i++) {
- r = (d->dev.config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3;
+ r = (d->dev.config[(i >> 1) + (I440FX_PAM + 1)] >> ((i & 1) * 4)) & 3;
update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r);
}
- smram = d->dev.config[0x72];
+ smram = d->dev.config[I440FX_SMRAM];
if ((d->smm_enabled && (smram & 0x08)) || (smram & 0x40)) {
cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000);
} else {
}
}
-void i440fx_set_smm(PCII440FXState *d, int val)
+static void i440fx_set_smm(int val, void *arg)
{
+ PCII440FXState *d = arg;
+
val = (val != 0);
if (d->smm_enabled != val) {
d->smm_enabled = val;
/* XXX: implement SMRAM.D_LOCK */
pci_default_write_config(dev, address, val, len);
- if ((address >= 0x59 && address <= 0x5f) || address == 0x72)
+ if (ranges_overlap(address, len, I440FX_PAM, I440FX_PAM_SIZE) ||
+ range_covers_byte(address, len, I440FX_SMRAM)) {
i440fx_update_memory_mappings(d);
+ }
}
static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
{
I440FXState *s = FROM_SYSBUS(I440FXState, dev);
- pci_host_config_register_ioport(0xcf8, s);
+ pci_host_conf_register_ioport(0xcf8, s);
pci_host_data_register_ioport(0xcfc, s);
return 0;
pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82441);
d->dev.config[0x08] = 0x02; // revision
pci_config_set_class(d->dev.config, PCI_CLASS_BRIDGE_HOST);
- d->dev.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
- d->dev.config[0x72] = 0x02; /* SMRAM */
+ d->dev.config[I440FX_SMRAM] = 0x02;
- vmstate_register(0, &vmstate_i440fx, d);
+ cpu_smm_register(&i440fx_set_smm, d);
return 0;
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic)
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size)
{
DeviceState *dev;
PCIBus *b;
*pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
piix3 = DO_UPCAST(PIIX3State, dev,
- pci_create_simple(b, -1, "PIIX3"));
+ pci_create_simple_multifunction(b, -1, true, "PIIX3"));
piix3->pic = pic;
pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, 4);
(*pi440fx_state)->piix3 = piix3;
*piix3_devfn = piix3->dev.devfn;
+ ram_size = ram_size / 8 / 1024 / 1024;
+ if (ram_size > 255)
+ ram_size = 255;
+ (*pi440fx_state)->dev.config[0x57]=ram_size;
+
return b;
}
uint8_t *pci_conf;
isa_bus_new(&d->dev.qdev);
- vmstate_register(0, &vmstate_piix3, d);
pci_conf = d->dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
- pci_conf[PCI_HEADER_TYPE] =
- PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
qemu_register_reset(piix3_reset, d);
return 0;
.qdev.name = "i440FX",
.qdev.desc = "Host bridge",
.qdev.size = sizeof(PCII440FXState),
+ .qdev.vmsd = &vmstate_i440fx,
.qdev.no_user = 1,
.init = i440fx_initfn,
.config_write = i440fx_write_config,
.qdev.name = "PIIX3",
.qdev.desc = "ISA bridge",
.qdev.size = sizeof(PIIX3State),
+ .qdev.vmsd = &vmstate_piix3,
.qdev.no_user = 1,
.init = piix3_initfn,
},{