diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/piix_pci.c | 95 |
1 files changed, 41 insertions, 54 deletions
diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 43f2da2c40..1557694470 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -55,63 +55,50 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) static uint32_t isa_page_descs[384 / 4]; static uint8_t smm_enabled; -static const uint32_t mar_addresses[15] = { - 0xa0000, - 0xc0000, - 0xc4000, - 0xc8000, - 0xcc000, - 0xd0000, - 0xd4000, - 0xd8000, - 0xdc000, - 0xe0000, - 0xe4000, - 0xe8000, - 0xec000, - 0xf0000, - 0x100000, -}; +static void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r) +{ + uint32_t addr; + + // printf("ISA mapping %08x-0x%08x: %d\n", start, end, r); + switch(r) { + case 3: + /* RAM */ + cpu_register_physical_memory(start, end - start, + start); + break; + case 1: + /* ROM (XXX: not quite correct) */ + cpu_register_physical_memory(start, end - start, + start | IO_MEM_ROM); + break; + case 2: + case 0: + /* XXX: should distinguish read/write cases */ + for(addr = start; addr < end; addr += 4096) { + cpu_register_physical_memory(addr, 4096, + isa_page_descs[(addr - 0xa0000) >> 12]); + } + break; + } +} static void i440fx_update_memory_mappings(PCIDevice *d) { int i, r; - uint32_t start, end, addr; - uint32_t smram, smbase, smsize; - - for(i = 0; i < 14; i++) { - r = (d->config[(i >> 1) + 0x61] >> ((i & 1) * 4)) & 3; - start = mar_addresses[i]; - end = mar_addresses[i + 1]; - // printf("ISA mapping %08x: %d\n", start, r); - switch(r) { - case 3: - /* RAM */ - cpu_register_physical_memory(start, end - start, - start); - break; - case 2: - /* ROM (XXX: not quite correct) */ - cpu_register_physical_memory(start, end - start, - start | IO_MEM_ROM); - break; - case 1: - case 0: - /* XXX: should distinguish read/write cases */ - for(addr = start; addr < end; addr += 4096) { - cpu_register_physical_memory(addr, 4096, - isa_page_descs[(addr - 0xa0000) >> 12]); - } - break; - } + uint32_t smram, addr; + + update_pam(d, 0xf0000, 0x100000, (d->config[0x59] >> 4) & 3); + for(i = 0; i < 12; i++) { + r = (d->config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3; + update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r); } - smram = le32_to_cpu(*(uint32_t *)(d->config + 0x6c)); - if ((smm_enabled && (smram & 0x80000000)) || (smram & (1 << 26))) { - /* Note: we assume the SMM area is in the 0xa0000-0x100000 range */ - smbase = (smram & 0xffff) << 16; - smsize = (((smram >> 20) & 0xf) + 1) << 16; - if (smbase >= 0xa0000 && (smbase + smsize) <= 0x100000) { - cpu_register_physical_memory(smbase, smsize, smbase); + smram = d->config[0x72]; + if ((smm_enabled && (smram & 0x08)) || (smram & 0x40)) { + cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000); + } else { + for(addr = 0xa0000; addr < 0xc0000; addr += 4096) { + cpu_register_physical_memory(addr, 4096, + isa_page_descs[(addr - 0xa0000) >> 12]); } } } @@ -142,7 +129,7 @@ static void i440fx_write_config(PCIDevice *d, { /* XXX: implement SMRAM.D_LOCK */ pci_default_write_config(d, address, val, len); - if ((address >= 0x61 && address <= 0x67) || address == 0x6c) + if ((address >= 0x59 && address <= 0x5f) || address == 0x72) i440fx_update_memory_mappings(d); } @@ -200,7 +187,7 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state) d->config[0x0b] = 0x06; // class_base = PCI_bridge d->config[0x0e] = 0x00; // header_type - d->config[0x6c] = 0x0a; /* SMRAM */ + d->config[0x72] = 0x02; /* SMRAM */ register_savevm("I440FX", 0, 1, i440fx_save, i440fx_load, d); *pi440fx_state = d; |