diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 39998791f2..f2ed136fda 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -29,6 +29,7 @@ #include "sysbus.h" #include "pci.h" #include "pci_host.h" +#include "apb_pci.h" /* debug APB */ //#define DEBUG_APB @@ -235,10 +236,10 @@ static int pci_pbm_init_device(SysBusDevice *dev) pci_apb_iowrite, s); sysbus_init_mmio(dev, 0x10000ULL, pci_ioport); /* mem_config */ - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x10ULL, pci_mem_config); /* mem_data */ - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data); return 0; } diff --git a/hw/apb_pci.h b/hw/apb_pci.h new file mode 100644 index 0000000000..8869f9d326 --- /dev/null +++ b/hw/apb_pci.h @@ -0,0 +1,9 @@ +#ifndef APB_PCI_H +#define APB_PCI_H + +#include "qemu-common.h" + +PCIBus *pci_apb_init(target_phys_addr_t special_base, + target_phys_addr_t mem_base, + qemu_irq *pic, PCIBus **bus2, PCIBus **bus3); +#endif diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index f3a8a7da12..089d1fba01 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -108,8 +108,8 @@ static int pci_grackle_init_device(SysBusDevice *dev) s = FROM_SYSBUS(GrackleState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); @@ -126,8 +126,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev) s = FROM_SYSBUS(GrackleState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 7e47fc9abc..8b8a80b898 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -31,6 +31,8 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0) #endif +#define LSI_MAX_DEVS 7 + #define LSI_SCNTL0_TRG 0x01 #define LSI_SCNTL0_AAP 0x02 #define LSI_SCNTL0_EPC 0x08 diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 76884570fb..571d8ced16 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -32,6 +32,8 @@ #include "flash.h" #include "mips.h" #include "pci.h" +#include "usb-uhci.h" +#include "vmware_vga.h" #include "qemu-char.h" #include "sysemu.h" #include "audio/audio.h" diff --git a/hw/msix.c b/hw/msix.c index 548ffd5c8b..4bc6147234 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -105,14 +105,6 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries, return 0; } -static void msix_free_irq_entries(PCIDevice *dev) -{ - int vector; - - for (vector = 0; vector < dev->msix_entries_nr; ++vector) - dev->msix_entry_used[vector] = 0; -} - /* Handle MSI-X capability config write. */ void msix_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) @@ -217,6 +209,15 @@ void msix_mmio_map(PCIDevice *d, int region_num, d->msix_mmio_index); } +static void msix_mask_all(struct PCIDevice *dev, unsigned nentries) +{ + int vector; + for (vector = 0; vector < nentries; ++vector) { + unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL; + dev->msix_table_page[offset] |= MSIX_VECTOR_MASK; + } +} + /* Initialize the MSI-X structures. Note: if MSI-X is supported, BAR size is * modified, it should be retrieved with msix_bar_size. */ int msix_init(struct PCIDevice *dev, unsigned short nentries, @@ -234,6 +235,7 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, sizeof *dev->msix_entry_used); dev->msix_table_page = qemu_mallocz(MSIX_PAGE_SIZE); + msix_mask_all(dev, nentries); dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read, msix_mmio_write, dev); @@ -261,6 +263,16 @@ err_index: return ret; } +static void msix_free_irq_entries(PCIDevice *dev) +{ + int vector; + + for (vector = 0; vector < dev->msix_entries_nr; ++vector) { + dev->msix_entry_used[vector] = 0; + msix_clr_pending(dev, vector); + } +} + /* Clean up resources for the device. */ int msix_uninit(PCIDevice *dev) { @@ -351,8 +363,10 @@ void msix_reset(PCIDevice *dev) if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return; msix_free_irq_entries(dev); - dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= MSIX_ENABLE_MASK; + dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= + ~dev->wmask[dev->msix_cap + MSIX_ENABLE_OFFSET]; memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE); + msix_mask_all(dev, dev->msix_entries_nr); } /* PCI spec suggests that devices make it possible for software to configure @@ -375,6 +389,18 @@ int msix_vector_use(PCIDevice *dev, unsigned vector) /* Mark vector as unused. */ void msix_vector_unuse(PCIDevice *dev, unsigned vector) { - if (vector < dev->msix_entries_nr && dev->msix_entry_used[vector]) - --dev->msix_entry_used[vector]; + if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) { + return; + } + if (--dev->msix_entry_used[vector]) { + return; + } + msix_clr_pending(dev, vector); +} + +void msix_unuse_all_vectors(PCIDevice *dev) +{ + if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) + return; + msix_free_irq_entries(dev); } diff --git a/hw/msix.h b/hw/msix.h index 39fa568f9c..a9f7993c39 100644 --- a/hw/msix.h +++ b/hw/msix.h @@ -25,6 +25,7 @@ uint32_t msix_bar_size(PCIDevice *dev); int msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); +void msix_unuse_all_vectors(PCIDevice *dev); void msix_notify(PCIDevice *dev, unsigned vector); diff --git a/hw/pc.c b/hw/pc.c index 7c791c4136..97964b27eb 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -25,6 +25,11 @@ #include "pc.h" #include "fdc.h" #include "pci.h" +#include "vmware_vga.h" +#include "usb-uhci.h" +#include "usb-ohci.h" +#include "prep_pci.h" +#include "apb_pci.h" #include "block.h" #include "sysemu.h" #include "audio/audio.h" diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index a254498143..081d6d1ac9 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -113,7 +113,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict) if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) { goto err; } - dev = pci_find_device(pci_find_host_bus(0), pci_bus, slot, 0); + dev = pci_find_device(pci_find_root_bus(0), pci_bus, slot, 0); if (!dev) { monitor_printf(mon, "no pci device with address %s\n", pci_addr); goto err; @@ -257,7 +257,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr) return; } - d = pci_find_device(pci_find_host_bus(0), bus, slot, 0); + d = pci_find_device(pci_find_root_bus(0), bus, slot, 0); if (!d) { monitor_printf(mon, "slot %d empty\n", slot); return; diff --git a/hw/pci.c b/hw/pci.c index 5b3461cd66..8cf008d31d 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -23,7 +23,6 @@ */ #include "hw.h" #include "pci.h" -#include "pci_host.h" #include "monitor.h" #include "net.h" #include "sysemu.h" @@ -146,7 +145,7 @@ static void pci_host_bus_register(int domain, PCIBus *bus) QLIST_INSERT_HEAD(&host_buses, host, next); } -PCIBus *pci_find_host_bus(int domain) +PCIBus *pci_find_root_bus(int domain) { struct PCIHostBus *host; @@ -239,13 +238,6 @@ int pci_bus_num(PCIBus *s) return s->parent_dev->config[PCI_SECONDARY_BUS]; } -static uint8_t pci_sub_bus(PCIBus *s) -{ - if (!s->parent_dev) - return 255; /* pci host bridge */ - return s->parent_dev->config[PCI_SUBORDINATE_BUS]; -} - static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) { PCIDevice *s = container_of(pv, PCIDevice, config); @@ -379,7 +371,7 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *s return -1; /* Note: QEMU doesn't implement domains other than 0 */ - if (!pci_find_bus(pci_find_host_bus(dom), bus)) + if (!pci_find_bus(pci_find_root_bus(dom), bus)) return -1; *domp = dom; @@ -409,7 +401,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) if (!devaddr) { *devfnp = -1; - return pci_find_bus(pci_find_host_bus(0), 0); + return pci_find_bus(pci_find_root_bus(0), 0); } if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) { @@ -417,7 +409,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) } *devfnp = slot << 3; - return pci_find_bus(pci_find_host_bus(0), bus); + return pci_find_bus(pci_find_root_bus(0), bus); } static void pci_init_cmask(PCIDevice *dev) @@ -434,15 +426,15 @@ static void pci_init_cmask(PCIDevice *dev) static void pci_init_wmask(PCIDevice *dev) { - int i; int config_size = pci_config_size(dev); dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; dev->wmask[PCI_INTERRUPT_LINE] = 0xff; pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i) - dev->wmask[i] = 0xff; + + memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, + config_size - PCI_CONFIG_HEADER_SIZE); } static void pci_init_wmask_bridge(PCIDevice *d) @@ -495,7 +487,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, uint8_t header_type) { if (devfn < 0) { - for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { + for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); + devfn += 8) { if (!bus->devices[devfn]) goto found; } @@ -637,24 +630,28 @@ static uint32_t pci_config_get_io_base(PCIDevice *d, val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8; if (d->config[base] & PCI_IO_RANGE_TYPE_32) { - val |= (uint32_t)pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16; + val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16; } return val; } -static uint64_t pci_config_get_memory_base(PCIDevice *d, uint32_t base) +static pcibus_t pci_config_get_memory_base(PCIDevice *d, uint32_t base) { - return ((uint64_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK) + return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK) << 16; } -static uint64_t pci_config_get_pref_base(PCIDevice *d, +static pcibus_t pci_config_get_pref_base(PCIDevice *d, uint32_t base, uint32_t upper) { - uint64_t val; - val = ((uint64_t)pci_get_word(d->config + base) & - PCI_PREF_RANGE_MASK) << 16; - val |= (uint64_t)pci_get_long(d->config + upper) << 32; + pcibus_t tmp; + pcibus_t val; + + tmp = (pcibus_t)pci_get_word(d->config + base); + val = (tmp & PCI_PREF_RANGE_MASK) << 16; + if (tmp & PCI_PREF_RANGE_TYPE_64) { + val |= (pcibus_t)pci_get_long(d->config + upper) << 32; + } return val; } @@ -720,83 +717,95 @@ static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size, } if (base > limit) { - no_map: - *addr = PCI_BAR_UNMAPPED; - *size = 0; - } else { - *addr = base; - *size = limit - base + 1; + goto no_map; } + *addr = base; + *size = limit - base + 1; + return; +no_map: + *addr = PCI_BAR_UNMAPPED; + *size = 0; +} + +static pcibus_t pci_bar_address(PCIDevice *d, + int reg, uint8_t type, pcibus_t size) +{ + pcibus_t new_addr, last_addr; + int bar = pci_bar(d, reg); + uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); + + if (type & PCI_BASE_ADDRESS_SPACE_IO) { + if (!(cmd & PCI_COMMAND_IO)) { + return PCI_BAR_UNMAPPED; + } + new_addr = pci_get_long(d->config + bar) & ~(size - 1); + last_addr = new_addr + size - 1; + /* NOTE: we have only 64K ioports on PC */ + if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) { + return PCI_BAR_UNMAPPED; + } + return new_addr; + } + + if (!(cmd & PCI_COMMAND_MEMORY)) { + return PCI_BAR_UNMAPPED; + } + if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { + new_addr = pci_get_quad(d->config + bar); + } else { + new_addr = pci_get_long(d->config + bar); + } + /* the ROM slot has a specific enable bit */ + if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) { + return PCI_BAR_UNMAPPED; + } + new_addr &= ~(size - 1); + last_addr = new_addr + size - 1; + /* NOTE: we do not support wrapping */ + /* XXX: as we cannot support really dynamic + mappings, we handle specific values as invalid + mappings. */ + if (last_addr <= new_addr || new_addr == 0 || + last_addr == PCI_BAR_UNMAPPED) { + return PCI_BAR_UNMAPPED; + } + + /* Now pcibus_t is 64bit. + * Check if 32 bit BAR wraps around explicitly. + * Without this, PC ide doesn't work well. + * TODO: remove this work around. + */ + if (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) { + return PCI_BAR_UNMAPPED; + } + + /* + * OS is allowed to set BAR beyond its addressable + * bits. For example, 32 bit OS can set 64bit bar + * to >4G. Check it. TODO: we might need to support + * it in the future for e.g. PAE. + */ + if (last_addr >= TARGET_PHYS_ADDR_MAX) { + return PCI_BAR_UNMAPPED; + } + + return new_addr; } static void pci_update_mappings(PCIDevice *d) { PCIIORegion *r; - int cmd, i; - pcibus_t last_addr, new_addr; - pcibus_t filtered_size; + int i; + pcibus_t new_addr, filtered_size; - cmd = pci_get_word(d->config + PCI_COMMAND); for(i = 0; i < PCI_NUM_REGIONS; i++) { r = &d->io_regions[i]; /* this region isn't registered */ - if (r->size == 0) + if (!r->size) continue; - if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - if (cmd & PCI_COMMAND_IO) { - new_addr = pci_get_long(d->config + pci_bar(d, i)); - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we have only 64K ioports on PC */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr >= 0x10000) { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - if (cmd & PCI_COMMAND_MEMORY) { - if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - new_addr = pci_get_quad(d->config + pci_bar(d, i)); - } else { - new_addr = pci_get_long(d->config + pci_bar(d, i)); - } - /* the ROM slot has a specific enable bit */ - if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) - goto no_mem_map; - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we do not support wrapping */ - /* XXX: as we cannot support really dynamic - mappings, we handle specific values as invalid - mappings. */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr == PCI_BAR_UNMAPPED || - - /* Now pcibus_t is 64bit. - * Check if 32 bit BAR wrap around explicitly. - * Without this, PC ide doesn't work well. - * TODO: remove this work around. - */ - (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) && - last_addr >= UINT32_MAX) || - - /* - * OS is allowed to set BAR beyond its addressable - * bits. For example, 32 bit OS can set 64bit bar - * to >4G. Check it. - */ - last_addr >= TARGET_PHYS_ADDR_MAX) { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - no_mem_map: - new_addr = PCI_BAR_UNMAPPED; - } - } + new_addr = pci_bar_address(d, i, r->type, r->size); /* bridge filtering */ filtered_size = r->size; @@ -986,7 +995,7 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d) base, limit); base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY); - limit= pci_config_get_memory_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY); + limit= pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_MEMORY); monitor_printf(mon, " memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n", base, limit); @@ -1032,7 +1041,7 @@ static void pci_for_each_device_under_bus(PCIBus *bus, PCIDevice *d; int devfn; - for(devfn = 0; devfn < 256; devfn++) { + for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { d = bus->devices[devfn]; if (d) fn(bus, d); @@ -1180,7 +1189,10 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num) /* try child bus */ QLIST_FOREACH(sec, &bus->child, sibling) { - if (pci_bus_num(sec) <= bus_num && bus_num <= pci_sub_bus(sec)) { + + if (!bus->parent_dev /* pci host bridge */ + || (pci_bus_num(sec) <= bus_num && + bus->parent_dev->config[PCI_SUBORDINATE_BUS])) { return pci_find_bus(sec, bus_num); } } diff --git a/hw/pci.h b/hw/pci.h index 9a56d0df6e..0baf69bd5d 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -101,14 +101,6 @@ typedef struct PCIIORegion { #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ #define PCI_COMMAND_MASTER 0x4 /* Enable bus master */ -#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ -#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ -#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ -#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ -#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ -#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ -#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ -#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ #define PCI_STATUS 0x06 /* 16 bits */ #define PCI_REVISION_ID 0x08 /* 8 bits */ #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ @@ -128,7 +120,6 @@ typedef struct PCIIORegion { #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ #define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ #define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ -#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ #define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ #define PCI_IO_LIMIT 0x1d #define PCI_IO_RANGE_TYPE_32 0x01 @@ -140,6 +131,7 @@ typedef struct PCIIORegion { #define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ #define PCI_PREF_MEMORY_LIMIT 0x26 #define PCI_PREF_RANGE_MASK (~0x0fUL) +#define PCI_PREF_RANGE_TYPE_64 0x01 #define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ #define PCI_PREF_LIMIT_UPPER32 0x2c #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */ @@ -293,11 +285,9 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, const char *default_devaddr); PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, const char *default_devaddr); -void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); -uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); int pci_bus_num(PCIBus *s); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d)); -PCIBus *pci_find_host_bus(int domain); +PCIBus *pci_find_root_bus(int domain); PCIBus *pci_find_bus(PCIBus *bus, int bus_num); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function); PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr); @@ -384,17 +374,10 @@ typedef struct { PCIConfigWriteFunc *config_write; /* pci config header type */ - uint8_t header_type; /* this is necessary for initialization - * code to know its header type before - * device specific code can initialize - * configuration space. - */ + uint8_t header_type; /* pcie stuff */ - int is_express; /* is this device pci express? - * initialization code needs to know this before - * each specific device initialization. - */ + int is_express; /* is this device pci express? */ } PCIDeviceInfo; void pci_qdev_register(PCIDeviceInfo *info); @@ -413,31 +396,6 @@ static inline uint32_t pci_config_size(PCIDevice *d) return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE; } -/* lsi53c895a.c */ -#define LSI_MAX_DEVS 7 - -/* vmware_vga.c */ -void pci_vmsvga_init(PCIBus *bus); - -/* usb-uhci.c */ -void usb_uhci_piix3_init(PCIBus *bus, int devfn); -void usb_uhci_piix4_init(PCIBus *bus, int devfn); - -/* usb-ohci.c */ -void usb_ohci_init_pci(struct PCIBus *bus, int devfn); - -/* prep_pci.c */ -PCIBus *pci_prep_init(qemu_irq *pic); - -/* apb_pci.c */ -PCIBus *pci_apb_init(target_phys_addr_t special_base, - target_phys_addr_t mem_base, - qemu_irq *pic, PCIBus **bus2, PCIBus **bus3); - -/* sh_pci.c */ -PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *pic, int devfn_min, int nirq); - /* These are not pci specific. Should move into a separate header. * Only pci.c uses them, so keep them here for now. */ diff --git a/hw/pci_host.c b/hw/pci_host.c index f4518dce72..eeb8deeafb 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -40,22 +40,18 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0) */ /* the helper functio to get a PCIDeice* for a given pci address */ -static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr) +static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) { - uint8_t bus_num = (addr >> 16) & 0xff; - uint8_t devfn = (addr >> 8) & 0xff; - return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); -} + uint8_t bus_num = addr >> 16; + uint8_t devfn = addr >> 8; -static inline uint32_t pci_addr_to_config(uint32_t addr) -{ - return addr & (PCI_CONFIG_SPACE_SIZE - 1); + return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); } void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) { - PCIDevice *pci_dev = pci_addr_to_dev(s, addr); - uint32_t config_addr = pci_addr_to_config(addr); + PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr); + uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); if (!pci_dev) return; @@ -67,29 +63,19 @@ void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) { - PCIDevice *pci_dev = pci_addr_to_dev(s, addr); - uint32_t config_addr = pci_addr_to_config(addr); + PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr); + uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); uint32_t val; + assert(len == 1 || len == 2 || len == 4); if (!pci_dev) { - switch(len) { - case 1: - val = 0xff; - break; - case 2: - val = 0xffff; - break; - default: - case 4: - val = 0xffffffff; - break; - } - } else { - val = pci_dev->config_read(pci_dev, config_addr, len); - PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n", - __func__, pci_dev->name, config_addr, val, len); + return ~0x0; } + val = pci_dev->config_read(pci_dev, config_addr, len); + PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n", + __func__, pci_dev->name, config_addr, val, len); + return val; } @@ -131,7 +117,7 @@ static CPUReadMemoryFunc * const pci_host_config_read[] = { &pci_host_config_readl, }; -int pci_host_config_register_io_memory(PCIHostState *s) +int pci_host_conf_register_mmio(PCIHostState *s) { return cpu_register_io_memory(pci_host_config_read, pci_host_config_write, s); @@ -171,7 +157,7 @@ static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = { &pci_host_config_readl_noswap, }; -int pci_host_config_register_io_memory_noswap(PCIHostState *s) +int pci_host_conf_register_mmio_noswap(PCIHostState *s) { return cpu_register_io_memory(pci_host_config_read_noswap, pci_host_config_write_noswap, s); @@ -195,7 +181,7 @@ static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr) return val; } -void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s) +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s) { register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s); register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s); @@ -218,7 +204,7 @@ static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = { pci_host_data_readl_mmio, }; -int pci_host_data_register_io_memory(PCIHostState *s) +int pci_host_data_register_mmio(PCIHostState *s) { return cpu_register_io_memory(pci_host_data_read_mmio, pci_host_data_write_mmio, diff --git a/hw/pci_host.h b/hw/pci_host.h index e5e877f4cd..a006687f8b 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -30,19 +30,22 @@ #include "sysbus.h" -typedef struct { +struct PCIHostState { SysBusDevice busdev; uint32_t config_reg; PCIBus *bus; -} PCIHostState; +}; + +void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); +uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); /* for mmio */ -int pci_host_config_register_io_memory(PCIHostState *s); -int pci_host_config_register_io_memory_noswap(PCIHostState *s); -int pci_host_data_register_io_memory(PCIHostState *s); +int pci_host_conf_register_mmio(PCIHostState *s); +int pci_host_conf_register_mmio_noswap(PCIHostState *s); +int pci_host_data_register_mmio(PCIHostState *s); /* for ioio */ -void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s); +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s); void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s); #endif /* PCI_HOST_H */ diff --git a/hw/pcie_host.c b/hw/pcie_host.c index b52fec6813..fbd6c3759f 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -46,7 +46,8 @@ /* a helper function to get a PCIDevice for a given mmconfig address */ -static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr) +static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s, + uint32_t mmcfg_addr) { return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr), PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)), @@ -56,7 +57,7 @@ static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr) static void pcie_mmcfg_data_write(PCIBus *s, uint32_t mmcfg_addr, uint32_t val, int len) { - PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr); + PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr); if (!pci_dev) return; @@ -65,31 +66,15 @@ static void pcie_mmcfg_data_write(PCIBus *s, PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len); } -static uint32_t pcie_mmcfg_data_read(PCIBus *s, - uint32_t mmcfg_addr, int len) +static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t addr, int len) { - PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr); - uint32_t val; + PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, addr); + assert(len == 1 || len == 2 || len == 4); if (!pci_dev) { - switch(len) { - case 1: - val = 0xff; - break; - case 2: - val = 0xffff; - break; - default: - case 4: - val = 0xffffffff; - break; - } - } else { - val = pci_dev->config_read(pci_dev, - PCIE_MMCFG_CONFOFFSET(mmcfg_addr), len); + return ~0x0; } - - return val; + return pci_dev->config_read(pci_dev, PCIE_MMCFG_CONFOFFSET(addr), len); } static void pcie_mmcfg_data_writeb(void *opaque, diff --git a/hw/pcie_host.h b/hw/pcie_host.h index a7771c912a..7754ac94e8 100644 --- a/hw/pcie_host.h +++ b/hw/pcie_host.h @@ -24,7 +24,7 @@ #include "pci_host.h" -typedef struct { +struct PCIExpressHost { PCIHostState pci; /* express part */ @@ -37,7 +37,7 @@ typedef struct { /* result of cpu_register_io_memory() to map MMCONFIG area */ int mmio_index; -} PCIExpressHost; +}; int pcie_host_init(PCIExpressHost *e); void pcie_host_mmcfg_unmap(PCIExpressHost *e); diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 5fb7d7be93..a44f941dc2 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -180,7 +180,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev) { 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; diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 3aa7489e28..2d00b61228 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -378,7 +378,7 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index); /* CFGDATA */ - index = pci_host_data_register_io_memory(&controller->pci_state); + index = pci_host_data_register_mmio(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index); diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index da868d302b..7579ddd340 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -29,6 +29,7 @@ #include "nvram.h" #include "pc.h" #include "pci.h" +#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 9b49a3dbdd..32fd03a900 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -32,6 +32,7 @@ #include "net.h" #include "isa.h" #include "pci.h" +#include "usb-ohci.h" #include "boards.h" #include "fw_cfg.h" #include "escc.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index cd561e10c6..eb758f2dab 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -29,6 +29,8 @@ #include "sysemu.h" #include "isa.h" #include "pci.h" +#include "prep_pci.h" +#include "usb-ohci.h" #include "ppc.h" #include "boards.h" #include "qemu-log.h" diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 223de3ae34..a72fb86d2e 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -293,13 +293,13 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers) controller->pci_dev = d; /* CFGADDR */ - index = pci_host_config_register_io_memory_noswap(&controller->pci_state); + index = pci_host_conf_register_mmio_noswap(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index); /* CFGDATA */ - index = pci_host_data_register_io_memory(&controller->pci_state); + index = pci_host_data_register_mmio(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index); diff --git a/hw/prep_pci.c b/hw/prep_pci.c index a338f81e11..19f028c7b7 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -25,6 +25,7 @@ #include "hw.h" #include "pci.h" #include "pci_host.h" +#include "prep_pci.h" typedef PCIHostState PREPPCIState; @@ -127,7 +128,7 @@ PCIBus *pci_prep_init(qemu_irq *pic) s->bus = pci_register_bus(NULL, "pci", prep_set_irq, prep_map_irq, pic, 0, 4); - pci_host_config_register_ioport(0xcf8, s); + pci_host_conf_register_ioport(0xcf8, s); pci_host_data_register_ioport(0xcfc, s); diff --git a/hw/prep_pci.h b/hw/prep_pci.h new file mode 100644 index 0000000000..cd6851288c --- /dev/null +++ b/hw/prep_pci.h @@ -0,0 +1,8 @@ +#ifndef QEMU_PREP_PCI_H +#define QEMU_PREP_PCI_H + +#include "qemu-common.h" + +PCIBus *pci_prep_init(qemu_irq *pic); + +#endif diff --git a/hw/r2d.c b/hw/r2d.c index c074a6e9c5..e4c02f05ef 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -29,6 +29,7 @@ #include "sysemu.h" #include "boards.h" #include "pci.h" +#include "sh_pci.h" #include "net.h" #include "sh7750_regs.h" #include "ide.h" diff --git a/hw/realview.c b/hw/realview.c index f0b8347340..3322c4fd5d 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -12,6 +12,7 @@ #include "primecell.h" #include "devices.h" #include "pci.h" +#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 4277b01c9f..abe4c7568b 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -24,6 +24,8 @@ #include "hw.h" #include "sh.h" #include "pci.h" +#include "pci_host.h" +#include "sh_pci.h" #include "bswap.h" typedef struct { diff --git a/hw/sh_pci.h b/hw/sh_pci.h new file mode 100644 index 0000000000..b1a5ec37c3 --- /dev/null +++ b/hw/sh_pci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_SH_PCI_H +#define QEMU_SH_PCI_H + +#include "qemu-common.h" + +PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + void *pic, int devfn_min, int nirq); + +#endif diff --git a/hw/sun4u.c b/hw/sun4u.c index 2189fa06af..a7a227bbec 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -23,6 +23,7 @@ */ #include "hw.h" #include "pci.h" +#include "apb_pci.h" #include "pc.h" #include "nvram.h" #include "fdc.h" diff --git a/hw/unin_pci.c b/hw/unin_pci.c index fe13e7b3eb..5b3f118fc5 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -84,8 +84,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev) /* Uninorth main bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); @@ -103,8 +103,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev) s = FROM_SYSBUS(UNINState, dev); // XXX: s = &pci_bridge[2]; - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; @@ -118,8 +118,8 @@ static int pci_unin_agp_init_device(SysBusDevice *dev) /* Uninorth AGP bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; @@ -133,8 +133,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev) /* Uninorth internal bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index 0f7f4de154..7ab3a98619 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -32,6 +32,7 @@ #include "pci.h" #include "pxa.h" #include "devices.h" +#include "usb-ohci.h" //#define DEBUG_OHCI /* Dump packet contents. */ diff --git a/hw/usb-ohci.h b/hw/usb-ohci.h new file mode 100644 index 0000000000..eefcef3602 --- /dev/null +++ b/hw/usb-ohci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_USB_OHCI_H +#define QEMU_USB_OHCI_H + +#include "qemu-common.h" + +void usb_ohci_init_pci(struct PCIBus *bus, int devfn); + +#endif + diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 8babb0265e..671916e056 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -29,6 +29,7 @@ #include "usb.h" #include "pci.h" #include "qemu-timer.h" +#include "usb-uhci.h" //#define DEBUG //#define DEBUG_DUMP_DATA diff --git a/hw/usb-uhci.h b/hw/usb-uhci.h new file mode 100644 index 0000000000..911948edb4 --- /dev/null +++ b/hw/usb-uhci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_USB_UHCI_H +#define QEMU_USB_UHCI_H + +#include "qemu-common.h" + +void usb_uhci_piix3_init(PCIBus *bus, int devfn); +void usb_uhci_piix4_init(PCIBus *bus, int devfn); + +#endif diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index a0d7d07ad2..153c6514f7 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -9,6 +9,7 @@ #include "sysbus.h" #include "pci.h" +#include "pci_host.h" typedef struct { SysBusDevice busdev; diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 226c616ee3..391f5b88c6 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -14,6 +14,7 @@ #include "net.h" #include "sysemu.h" #include "pci.h" +#include "usb-ohci.h" #include "boards.h" /* Primary interrupt controller. */ diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index aebcf9d0d1..d222ce03fe 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -185,8 +185,10 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case VIRTIO_PCI_QUEUE_PFN: pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; - if (pa == 0) - virtio_pci_reset(&proxy->pci_dev.qdev); + if (pa == 0) { + virtio_reset(proxy->vdev); + msix_unuse_all_vectors(&proxy->pci_dev); + } else virtio_queue_set_addr(vdev, vdev->queue_sel, pa); break; @@ -199,8 +201,10 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case VIRTIO_PCI_STATUS: vdev->status = val & 0xFF; - if (vdev->status == 0) - virtio_pci_reset(&proxy->pci_dev.qdev); + if (vdev->status == 0) { + virtio_reset(proxy->vdev); + msix_unuse_all_vectors(&proxy->pci_dev); + } break; case VIRTIO_MSI_CONFIG_VECTOR: msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 33e876e959..bb3410105f 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -24,6 +24,7 @@ #include "hw.h" #include "console.h" #include "pci.h" +#include "vmware_vga.h" #define VERBOSE #undef DIRECT_VRAM diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h new file mode 100644 index 0000000000..2e0813c81b --- /dev/null +++ b/hw/vmware_vga.h @@ -0,0 +1,9 @@ +#ifndef QEMU_VMWARE_VGA_H +#define QEMU_VMWARE_VGA_H + +#include "qemu-common.h" + +/* vmware_vga.c */ +void pci_vmsvga_init(PCIBus *bus); + +#endif diff --git a/qemu-common.h b/qemu-common.h index b1e038bd00..57af677f07 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -198,6 +198,8 @@ typedef struct i2c_bus i2c_bus; typedef struct i2c_slave i2c_slave; typedef struct SMBusDevice SMBusDevice; typedef struct QEMUTimer QEMUTimer; +typedef struct PCIHostState PCIHostState; +typedef struct PCIExpressHost PCIExpressHost; typedef struct PCIBus PCIBus; typedef struct PCIDevice PCIDevice; typedef struct SerialState SerialState;