diff options
author | Anthony Liguori | 2013-03-26 22:16:43 +0100 |
---|---|---|
committer | Anthony Liguori | 2013-03-26 22:16:43 +0100 |
commit | 404e7a4f4af753bd2aef649adf79e7434fb6dc31 (patch) | |
tree | 43a43089f2e5cab27bd5d514ba2e9753d9c760af /hw/pci/pci_bridge.c | |
parent | Merge remote-tracking branch 'quintela/migration.next' into staging (diff) | |
parent | pcie: Add endpoint capability initialization wrapper (diff) | |
download | qemu-404e7a4f4af753bd2aef649adf79e7434fb6dc31.tar.gz qemu-404e7a4f4af753bd2aef649adf79e7434fb6dc31.tar.xz qemu-404e7a4f4af753bd2aef649adf79e7434fb6dc31.zip |
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
virtio,pci,qom
Work by Alex to support VGA assignment,
pci and virtio fixes by Stefan, Jason and myself, and a
new qmp event for hotplug support by myself.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Tue 26 Mar 2013 02:02:24 PM CDT using RSA key ID D28D5469
# gpg: Can't check signature: public key not found
# By Alex Williamson (13) and others
# Via Michael S. Tsirkin
* mst/tags/for_anthony: (23 commits)
pcie: Add endpoint capability initialization wrapper
roms: switch oldnoconfig to olddefconfig
pcie: Mangle types to match topology
pci: Create and use API to determine root buses
pci: Create pci_bus_is_express helper
pci: Q35, Root Ports, and Switches create PCI Express buses
pci: Allow PCI bus creation interfaces to specify the type of bus
pci: Move PCI and PCIE type defines
pci: Create and register a new PCI Express TypeInfo
exec: assert that RAMBlock size is non-zero
pci: refuse empty ROM files
pci_bridge: Remove duplicate IRQ swizzle function
pci_bridge: Use a default map_irq function
pci: Fix INTx routing notifier recursion
pci_bridge: drop formatting from source
pci_bridge: factor out common code
pci: Teach PCI Bridges about VGA routing
pci: Add PCI VGA helpers
virtio-pci: guest notifier mask without non-irqfd
virtio-net: remove layout assumptions for mq ctrl
...
Diffstat (limited to 'hw/pci/pci_bridge.c')
-rw-r--r-- | hw/pci/pci_bridge.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 995842a72d..24be6c5067 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -151,6 +151,28 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, memory_region_add_subregion_overlap(parent_space, base, alias, 1); } +static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent, + MemoryRegion *alias_vga) +{ + uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL); + + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], + "pci_bridge_vga_io_lo", &br->address_space_io, + QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE); + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], + "pci_bridge_vga_io_hi", &br->address_space_io, + QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE); + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], + "pci_bridge_vga_mem", &br->address_space_mem, + QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE); + + if (brctl & PCI_BRIDGE_CTL_VGA) { + pci_register_vga(&br->dev, &alias_vga[QEMU_PCI_VGA_MEM], + &alias_vga[QEMU_PCI_VGA_IO_LO], + &alias_vga[QEMU_PCI_VGA_IO_HI]); + } +} + static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br) { PCIBus *parent = br->dev.bus; @@ -175,7 +197,8 @@ static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br) &br->address_space_io, parent->address_space_io, cmd & PCI_COMMAND_IO); - /* TODO: optinal VGA and VGA palette snooping support. */ + + pci_bridge_init_vga_aliases(br, parent, w->alias_vga); return w; } @@ -187,6 +210,7 @@ static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w) memory_region_del_subregion(parent->address_space_io, &w->alias_io); memory_region_del_subregion(parent->address_space_mem, &w->alias_mem); memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem); + pci_unregister_vga(&br->dev); } static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w) @@ -194,6 +218,9 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w) memory_region_destroy(&w->alias_io); memory_region_destroy(&w->alias_mem); memory_region_destroy(&w->alias_pref_mem); + memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_LO]); + memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_HI]); + memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_MEM]); g_free(w); } @@ -227,7 +254,10 @@ void pci_bridge_write_config(PCIDevice *d, /* memory base/limit, prefetchable base/limit and io base/limit upper 16 */ - ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) { + ranges_overlap(address, len, PCI_MEMORY_BASE, 20) || + + /* vga enable */ + ranges_overlap(address, len, PCI_BRIDGE_CONTROL, 2)) { pci_bridge_update_mappings(s); } @@ -298,7 +328,7 @@ void pci_bridge_reset(DeviceState *qdev) } /* default qdev initialization function for PCI-to-PCI bridge */ -int pci_bridge_initfn(PCIDevice *dev) +int pci_bridge_initfn(PCIDevice *dev, const char *typename) { PCIBus *parent = dev->bus; PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); @@ -306,6 +336,16 @@ int pci_bridge_initfn(PCIDevice *dev) pci_word_test_and_set_mask(dev->config + PCI_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); + + /* + * TODO: We implement VGA Enable in the Bridge Control Register + * therefore per the PCI to PCI bridge spec we must also implement + * VGA Palette Snooping. When done, set this bit writable: + * + * pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, + * PCI_COMMAND_VGA_PALETTE); + */ + pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI); dev->config[PCI_HEADER_TYPE] = (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) | @@ -323,10 +363,9 @@ int pci_bridge_initfn(PCIDevice *dev) br->bus_name = dev->qdev.id; } - qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev, - br->bus_name); + qbus_create_inplace(&sec_bus->qbus, typename, &dev->qdev, br->bus_name); sec_bus->parent_dev = dev; - sec_bus->map_irq = br->map_irq; + sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn; sec_bus->address_space_mem = &br->address_space_mem; memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX); sec_bus->address_space_io = &br->address_space_io; |