piix_pci.c revision 86797937017f52bff088d02edf64fb931177a7ea
186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* 286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * QEMU i440FX/PIIX3 PCI Bridge Emulation 386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Copyright (c) 2006 Fabrice Bellard 586797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Permission is hereby granted, free of charge, to any person obtaining a copy 786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * of this software and associated documentation files (the "Software"), to deal 886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * in the Software without restriction, including without limitation the rights 986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * copies of the Software, and to permit persons to whom the Software is 1186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * furnished to do so, subject to the following conditions: 1286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 1386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * The above copyright notice and this permission notice shall be included in 1486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * all copies or substantial portions of the Software. 1586797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 1686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE. 2386797937017f52bff088d02edf64fb931177a7eaJun Nakajima */ 2486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 2586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "hw.h" 2686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "pc.h" 2786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "pci.h" 2886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 2986797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef uint32_t pci_addr_t; 3086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "pci_host.h" 3186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 3286797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef PCIHostState I440FXState; 3386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 3486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val) 3586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 3686797937017f52bff088d02edf64fb931177a7eaJun Nakajima I440FXState *s = opaque; 3786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->config_reg = val; 3886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 3986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 4086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t i440fx_addr_readl(void* opaque, uint32_t addr) 4186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 4286797937017f52bff088d02edf64fb931177a7eaJun Nakajima I440FXState *s = opaque; 4386797937017f52bff088d02edf64fb931177a7eaJun Nakajima return s->config_reg; 4486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 4586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 4686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void piix3_set_irq(qemu_irq *pic, int irq_num, int level); 4786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 4886797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* return the global irq number corresponding to a given device irq 4986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pin. We could also use the bus number to have a more precise 5086797937017f52bff088d02edf64fb931177a7eaJun Nakajima mapping. */ 5186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) 5286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 5386797937017f52bff088d02edf64fb931177a7eaJun Nakajima int slot_addend; 5486797937017f52bff088d02edf64fb931177a7eaJun Nakajima slot_addend = (pci_dev->devfn >> 3) - 1; 5586797937017f52bff088d02edf64fb931177a7eaJun Nakajima return (irq_num + slot_addend) & 3; 5686797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 5786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 5886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic target_phys_addr_t isa_page_descs[384 / 4]; 5986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint8_t smm_enabled; 6086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pci_irq_levels[4]; 6186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 6286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void update_pam(PCIDevice *d, uint32_t start, uint32_t end, int r) 6386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 6486797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint32_t addr; 6586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 6686797937017f52bff088d02edf64fb931177a7eaJun Nakajima // printf("ISA mapping %08x-0x%08x: %d\n", start, end, r); 6786797937017f52bff088d02edf64fb931177a7eaJun Nakajima switch(r) { 6886797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 3: 6986797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* RAM */ 7086797937017f52bff088d02edf64fb931177a7eaJun Nakajima cpu_register_physical_memory(start, end - start, 7186797937017f52bff088d02edf64fb931177a7eaJun Nakajima start); 7286797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 7386797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 1: 7486797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* ROM (XXX: not quite correct) */ 7586797937017f52bff088d02edf64fb931177a7eaJun Nakajima cpu_register_physical_memory(start, end - start, 7686797937017f52bff088d02edf64fb931177a7eaJun Nakajima start | IO_MEM_ROM); 7786797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 7886797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 2: 7986797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 0: 8086797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* XXX: should distinguish read/write cases */ 8186797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(addr = start; addr < end; addr += 4096) { 8286797937017f52bff088d02edf64fb931177a7eaJun Nakajima cpu_register_physical_memory(addr, 4096, 8386797937017f52bff088d02edf64fb931177a7eaJun Nakajima isa_page_descs[(addr - 0xa0000) >> 12]); 8486797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 8586797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 8686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 8786797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 8886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 8986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void i440fx_update_memory_mappings(PCIDevice *d) 9086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 9186797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i, r; 9286797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint32_t smram, addr; 9386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 9486797937017f52bff088d02edf64fb931177a7eaJun Nakajima update_pam(d, 0xf0000, 0x100000, (d->config[0x59] >> 4) & 3); 9586797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(i = 0; i < 12; i++) { 9686797937017f52bff088d02edf64fb931177a7eaJun Nakajima r = (d->config[(i >> 1) + 0x5a] >> ((i & 1) * 4)) & 3; 9786797937017f52bff088d02edf64fb931177a7eaJun Nakajima update_pam(d, 0xc0000 + 0x4000 * i, 0xc0000 + 0x4000 * (i + 1), r); 9886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 9986797937017f52bff088d02edf64fb931177a7eaJun Nakajima smram = d->config[0x72]; 10086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if ((smm_enabled && (smram & 0x08)) || (smram & 0x40)) { 10186797937017f52bff088d02edf64fb931177a7eaJun Nakajima cpu_register_physical_memory(0xa0000, 0x20000, 0xa0000); 10286797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 10386797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(addr = 0xa0000; addr < 0xc0000; addr += 4096) { 10486797937017f52bff088d02edf64fb931177a7eaJun Nakajima cpu_register_physical_memory(addr, 4096, 10586797937017f52bff088d02edf64fb931177a7eaJun Nakajima isa_page_descs[(addr - 0xa0000) >> 12]); 10686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 10786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 10886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 10986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 11086797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid i440fx_set_smm(PCIDevice *d, int val) 11186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 11286797937017f52bff088d02edf64fb931177a7eaJun Nakajima val = (val != 0); 11386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (smm_enabled != val) { 11486797937017f52bff088d02edf64fb931177a7eaJun Nakajima smm_enabled = val; 11586797937017f52bff088d02edf64fb931177a7eaJun Nakajima i440fx_update_memory_mappings(d); 11686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 11786797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 11886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 11986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 12086797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* XXX: suppress when better memory API. We make the assumption that 12186797937017f52bff088d02edf64fb931177a7eaJun Nakajima no device (in particular the VGA) changes the memory mappings in 12286797937017f52bff088d02edf64fb931177a7eaJun Nakajima the 0xa0000-0x100000 range */ 12386797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid i440fx_init_memory_mappings(PCIDevice *d) 12486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 12586797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i; 12686797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(i = 0; i < 96; i++) { 12786797937017f52bff088d02edf64fb931177a7eaJun Nakajima isa_page_descs[i] = cpu_get_physical_page_desc(0xa0000 + i * 0x1000); 12886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 12986797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 13086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 13186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void i440fx_write_config(PCIDevice *d, 13286797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint32_t address, uint32_t val, int len) 13386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 13486797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* XXX: implement SMRAM.D_LOCK */ 13586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_default_write_config(d, address, val, len); 13686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if ((address >= 0x59 && address <= 0x5f) || address == 0x72) 13786797937017f52bff088d02edf64fb931177a7eaJun Nakajima i440fx_update_memory_mappings(d); 13886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 13986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 14086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void i440fx_save(QEMUFile* f, void *opaque) 14186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 14286797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 14386797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i; 14486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 14586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_device_save(d, f); 14686797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &smm_enabled); 14786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 14886797937017f52bff088d02edf64fb931177a7eaJun Nakajima for (i = 0; i < 4; i++) 14986797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_be32(f, pci_irq_levels[i]); 15086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 15186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 15286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int i440fx_load(QEMUFile* f, void *opaque, int version_id) 15386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 15486797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 15586797937017f52bff088d02edf64fb931177a7eaJun Nakajima int ret, i; 15686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 15786797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (version_id > 2) 15886797937017f52bff088d02edf64fb931177a7eaJun Nakajima return -EINVAL; 15986797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = pci_device_load(d, f); 16086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (ret < 0) 16186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return ret; 16286797937017f52bff088d02edf64fb931177a7eaJun Nakajima i440fx_update_memory_mappings(d); 16386797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &smm_enabled); 16486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 16586797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (version_id >= 2) 16686797937017f52bff088d02edf64fb931177a7eaJun Nakajima for (i = 0; i < 4; i++) 16786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_irq_levels[i] = qemu_get_be32(f); 16886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 16986797937017f52bff088d02edf64fb931177a7eaJun Nakajima return 0; 17086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 17186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 17286797937017f52bff088d02edf64fb931177a7eaJun NakajimaPCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic) 17386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 17486797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIBus *b; 17586797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d; 17686797937017f52bff088d02edf64fb931177a7eaJun Nakajima I440FXState *s; 17786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 17886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s = qemu_mallocz(sizeof(I440FXState)); 17986797937017f52bff088d02edf64fb931177a7eaJun Nakajima b = pci_register_bus(NULL, "pci", 18086797937017f52bff088d02edf64fb931177a7eaJun Nakajima piix3_set_irq, pci_slot_get_pirq, pic, 0, 4); 18186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->bus = b; 18286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 18386797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s); 18486797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s); 18586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 18686797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s); 18786797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s); 18886797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s); 18986797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s); 19086797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s); 19186797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s); 19286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 19386797937017f52bff088d02edf64fb931177a7eaJun Nakajima d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0, 19486797937017f52bff088d02edf64fb931177a7eaJun Nakajima NULL, i440fx_write_config); 19586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 19686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL); 19786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441); 19886797937017f52bff088d02edf64fb931177a7eaJun Nakajima d->config[0x08] = 0x02; // revision 19986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); 20086797937017f52bff088d02edf64fb931177a7eaJun Nakajima d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type 20186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 20286797937017f52bff088d02edf64fb931177a7eaJun Nakajima d->config[0x72] = 0x02; /* SMRAM */ 20386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 20486797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d); 20586797937017f52bff088d02edf64fb931177a7eaJun Nakajima *pi440fx_state = d; 20686797937017f52bff088d02edf64fb931177a7eaJun Nakajima return b; 20786797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 20886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 20986797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* PIIX3 PCI to ISA bridge */ 21086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 21186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic PCIDevice *piix3_dev; 21286797937017f52bff088d02edf64fb931177a7eaJun NakajimaPCIDevice *piix4_dev; 21386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 21486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void piix3_set_irq(qemu_irq *pic, int irq_num, int level) 21586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 21686797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i, pic_irq, pic_level; 21786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 21886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_irq_levels[irq_num] = level; 21986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 22086797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* now we change the pic irq level according to the piix irq mappings */ 22186797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* XXX: optimize */ 22286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_irq = piix3_dev->config[0x60 + irq_num]; 22386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (pic_irq < 16) { 22486797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* The pic level is the logical OR of all the PCI irqs mapped 22586797937017f52bff088d02edf64fb931177a7eaJun Nakajima to it */ 22686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_level = 0; 22786797937017f52bff088d02edf64fb931177a7eaJun Nakajima for (i = 0; i < 4; i++) { 22886797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (pic_irq == piix3_dev->config[0x60 + i]) 22986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_level |= pci_irq_levels[i]; 23086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 23186797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_set_irq(pic[pic_irq], pic_level); 23286797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 23386797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 23486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 23586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void piix3_reset(void *opaque) 23686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 23786797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 23886797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t *pci_conf = d->config; 23986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 24086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x04] = 0x07; // master, memory and I/O 24186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x05] = 0x00; 24286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x06] = 0x00; 24386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x07] = 0x02; // PCI_status_devsel_medium 24486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4c] = 0x4d; 24586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4e] = 0x03; 24686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4f] = 0x00; 24786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x60] = 0x80; 24886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x61] = 0x80; 24986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x62] = 0x80; 25086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x63] = 0x80; 25186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x69] = 0x02; 25286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x70] = 0x80; 25386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x76] = 0x0c; 25486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x77] = 0x0c; 25586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x78] = 0x02; 25686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x79] = 0x00; 25786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x80] = 0x00; 25886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x82] = 0x00; 25986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa0] = 0x08; 26086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa2] = 0x00; 26186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa3] = 0x00; 26286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa4] = 0x00; 26386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa5] = 0x00; 26486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa6] = 0x00; 26586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa7] = 0x00; 26686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa8] = 0x0f; 26786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xaa] = 0x00; 26886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xab] = 0x00; 26986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xac] = 0x00; 27086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xae] = 0x00; 27186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 27286797937017f52bff088d02edf64fb931177a7eaJun Nakajima memset(pci_irq_levels, 0, sizeof(pci_irq_levels)); 27386797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 27486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 27586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void piix4_reset(void *opaque) 27686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 27786797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 27886797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t *pci_conf = d->config; 27986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 28086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x04] = 0x07; // master, memory and I/O 28186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x05] = 0x00; 28286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x06] = 0x00; 28386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x07] = 0x02; // PCI_status_devsel_medium 28486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4c] = 0x4d; 28586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4e] = 0x03; 28686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x4f] = 0x00; 28786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10 28886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10 28986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11 29086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11 29186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x69] = 0x02; 29286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x70] = 0x80; 29386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x76] = 0x0c; 29486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x77] = 0x0c; 29586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x78] = 0x02; 29686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x79] = 0x00; 29786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x80] = 0x00; 29886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0x82] = 0x00; 29986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa0] = 0x08; 30086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa2] = 0x00; 30186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa3] = 0x00; 30286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa4] = 0x00; 30386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa5] = 0x00; 30486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa6] = 0x00; 30586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa7] = 0x00; 30686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xa8] = 0x0f; 30786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xaa] = 0x00; 30886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xab] = 0x00; 30986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xac] = 0x00; 31086797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[0xae] = 0x00; 31186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 31286797937017f52bff088d02edf64fb931177a7eaJun Nakajima memset(pci_irq_levels, 0, sizeof(pci_irq_levels)); 31386797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 31486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 31586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void piix_save(QEMUFile* f, void *opaque) 31686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 31786797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 31886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_device_save(d, f); 31986797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 32086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 32186797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int piix_load(QEMUFile* f, void *opaque, int version_id) 32286797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 32386797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d = opaque; 32486797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (version_id != 2) 32586797937017f52bff088d02edf64fb931177a7eaJun Nakajima return -EINVAL; 32686797937017f52bff088d02edf64fb931177a7eaJun Nakajima return pci_device_load(d, f); 32786797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 32886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 32986797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint piix3_init(PCIBus *bus, int devfn) 33086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 33186797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d; 33286797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t *pci_conf; 33386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 33486797937017f52bff088d02edf64fb931177a7eaJun Nakajima d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice), 33586797937017f52bff088d02edf64fb931177a7eaJun Nakajima devfn, NULL, NULL); 33686797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_savevm("PIIX3", 0, 2, piix_save, piix_load, d); 33786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 33886797937017f52bff088d02edf64fb931177a7eaJun Nakajima piix3_dev = d; 33986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf = d->config; 34086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 34186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); 34286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) 34386797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA); 34486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[PCI_HEADER_TYPE] = 34586797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic 34686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 34786797937017f52bff088d02edf64fb931177a7eaJun Nakajima piix3_reset(d); 34886797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_register_reset(piix3_reset, 0, d); 34986797937017f52bff088d02edf64fb931177a7eaJun Nakajima return d->devfn; 35086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 35186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 35286797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint piix4_init(PCIBus *bus, int devfn) 35386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 35486797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCIDevice *d; 35586797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t *pci_conf; 35686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 35786797937017f52bff088d02edf64fb931177a7eaJun Nakajima d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice), 35886797937017f52bff088d02edf64fb931177a7eaJun Nakajima devfn, NULL, NULL); 35986797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_savevm("PIIX4", 0, 2, piix_save, piix_load, d); 36086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 36186797937017f52bff088d02edf64fb931177a7eaJun Nakajima piix4_dev = d; 36286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf = d->config; 36386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 36486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); 36586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge 36686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA); 36786797937017f52bff088d02edf64fb931177a7eaJun Nakajima pci_conf[PCI_HEADER_TYPE] = 36886797937017f52bff088d02edf64fb931177a7eaJun Nakajima PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic 36986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 37086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 37186797937017f52bff088d02edf64fb931177a7eaJun Nakajima piix4_reset(d); 37286797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_register_reset(piix4_reset, 0, d); 37386797937017f52bff088d02edf64fb931177a7eaJun Nakajima return d->devfn; 37486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 375