Signed-off-by: Hu Tao <hu...@cn.fujitsu.com> --- hw/pci-host/piix.c | 123 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 47 deletions(-)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 1c5c761..218aca2 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -38,16 +38,6 @@ * http://download.intel.com/design/chipsets/datashts/29054901.pdf */ -#define TYPE_I440FX_DEVICE "i440FX" -#define I440FX_DEVICE(obj) \ - OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_DEVICE) - -typedef struct I440FXState { - PCIHostState parent_obj; - MemoryRegion *address_space_io; - MemoryRegion *pci_address_space; -} I440FXState; - #define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ #define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */ #define XEN_PIIX_NUM_PIRQS 128ULL @@ -102,8 +92,25 @@ struct I440FXPMCState { PAMMemoryRegion pam_regions[13]; MemoryRegion smram_region; uint8_t smm_enabled; + ram_addr_t ram_size; + hwaddr pci_hole_start; + hwaddr pci_hole_size; + hwaddr pci_hole64_start; + hwaddr pci_hole64_size; }; +#define TYPE_I440FX_DEVICE "i440FX" +#define I440FX_DEVICE(obj) \ + OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_DEVICE) + +typedef struct I440FXState { + PCIHostState parent_obj; + MemoryRegion *address_space_io; + MemoryRegion *pci_address_space; + + PIIX3State piix3; + I440FXPMCState pmc; +} I440FXState; #define I440FX_PAM 0x59 #define I440FX_PAM_SIZE 7 @@ -221,16 +228,63 @@ static int i440fx_realize(SysBusDevice *dev) sysbus_add_io(dev, 0xcfc, &s->data_mem); sysbus_init_ioports(&s->busdev, 0xcfc, 4); + qdev_set_parent_bus(DEVICE(&f->pmc), BUS(s->bus)); + qdev_init_nofail(DEVICE(&f->pmc)); + return 0; } static void i440fx_initfn(Object *obj) { + I440FXState *f = I440FX_DEVICE(obj); + + object_initialize(&f->pmc, TYPE_I440FX_PMC_DEVICE); + object_property_add_child(obj, "pmc", OBJECT(&f->pmc), NULL); + qdev_prop_set_uint32(DEVICE(&f->pmc), "addr", PCI_DEVFN(0, 0)); } static int i440fx_pmc_initfn(PCIDevice *dev) { I440FXPMCState *d = I440FX_PMC_DEVICE(dev); + ram_addr_t ram_size; + int i; + + g_assert(d->system_memory != NULL); + g_assert(d->pci_address_space != NULL); + g_assert(d->ram_memory != NULL); + + memory_region_init_alias(&d->pci_hole, "pci-hole", d->pci_address_space, + d->pci_hole_start, d->pci_hole_size); + memory_region_add_subregion(d->system_memory, d->pci_hole_start, + &d->pci_hole); + memory_region_init_alias(&d->pci_hole_64bit, "pci-hole64", + d->pci_address_space, + d->pci_hole64_start, d->pci_hole64_size); + if (d->pci_hole64_size) { + memory_region_add_subregion(d->system_memory, d->pci_hole64_start, + &d->pci_hole_64bit); + } + memory_region_init_alias(&d->smram_region, "smram-region", + d->pci_address_space, 0xa0000, 0x20000); + memory_region_add_subregion_overlap(d->system_memory, 0xa0000, + &d->smram_region, 1); + memory_region_set_enabled(&d->smram_region, false); + + init_pam(d->ram_memory, d->system_memory, d->pci_address_space, + &d->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); + for (i = 0; i < 12; ++i) { + init_pam(d->ram_memory, d->system_memory, d->pci_address_space, + &d->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, + PAM_EXPAN_SIZE); + } + + ram_size = d->ram_size / 8 / 1024 / 1024; + if (ram_size > 255) { + ram_size = 255; + } + d->dev.config[0x57] = ram_size; + + i440fx_pmc_update_memory_mappings(d); d->dev.config[I440FX_SMRAM] = 0x02; @@ -251,12 +305,10 @@ static PCIBus *i440fx_common_init(const char *device_name, MemoryRegion *pci_address_space, MemoryRegion *ram_memory) { - PCIDevice *d; PCIHostState *s; PIIX3State *piix3; I440FXPMCState *f; I440FXState *i440fx; - unsigned i; i440fx = I440FX_DEVICE(object_new(TYPE_I440FX_DEVICE)); s = PCI_HOST_BRIDGE(i440fx); @@ -264,38 +316,22 @@ static PCIBus *i440fx_common_init(const char *device_name, i440fx->address_space_io = address_space_io; i440fx->pci_address_space = pci_address_space; - object_property_add_child(qdev_get_machine(), "i440fx", - OBJECT(i440fx), NULL); - qdev_set_parent_bus(DEVICE(i440fx), sysbus_get_default()); - qdev_init_nofail(DEVICE(i440fx)); + /* FIXME these should be derived */ + i440fx->pmc.pci_hole_start = pci_hole_start; + i440fx->pmc.pci_hole_size = pci_hole_size; + i440fx->pmc.pci_hole64_start = pci_hole64_start; + i440fx->pmc.pci_hole64_size = pci_hole64_size; - d = pci_create_simple(s->bus, 0, device_name); - f = I440FX_PMC_DEVICE(d); + f = &i440fx->pmc; + f->ram_size = ram_size; f->system_memory = address_space_mem; f->pci_address_space = pci_address_space; f->ram_memory = ram_memory; - memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space, - pci_hole_start, pci_hole_size); - memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole); - memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64", - f->pci_address_space, - pci_hole64_start, pci_hole64_size); - if (pci_hole64_size) { - memory_region_add_subregion(f->system_memory, pci_hole64_start, - &f->pci_hole_64bit); - } - memory_region_init_alias(&f->smram_region, "smram-region", - f->pci_address_space, 0xa0000, 0x20000); - memory_region_add_subregion_overlap(f->system_memory, 0xa0000, - &f->smram_region, 1); - memory_region_set_enabled(&f->smram_region, false); - init_pam(f->ram_memory, f->system_memory, f->pci_address_space, - &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); - for (i = 0; i < 12; ++i) { - init_pam(f->ram_memory, f->system_memory, f->pci_address_space, - &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, - PAM_EXPAN_SIZE); - } + + object_property_add_child(qdev_get_machine(), "i440fx", + OBJECT(i440fx), NULL); + qdev_set_parent_bus(DEVICE(i440fx), sysbus_get_default()); + qdev_init_nofail(DEVICE(i440fx)); /* Xen supports additional interrupt routes from the PCI devices to * the IOAPIC: the four pins of each PCI device on the bus are also @@ -318,13 +354,6 @@ static PCIBus *i440fx_common_init(const char *device_name, *piix3_devfn = piix3->dev.devfn; - ram_size = ram_size / 8 / 1024 / 1024; - if (ram_size > 255) - ram_size = 255; - f->dev.config[0x57] = ram_size; - - i440fx_pmc_update_memory_mappings(f); - return s->bus; } -- 1.8.3.1