summary refs log tree commit diff stats
path: root/hw/pci/pci_bridge.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-03-26 16:16:43 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-03-26 16:16:43 -0500
commit404e7a4f4af753bd2aef649adf79e7434fb6dc31 (patch)
tree43a43089f2e5cab27bd5d514ba2e9753d9c760af /hw/pci/pci_bridge.c
parent18501ae6e825d8da72369fd091018ef71071bd87 (diff)
parent6214e73cc5b75a4f8d89a70d71727edfa47a81b3 (diff)
downloadfocaccia-qemu-404e7a4f4af753bd2aef649adf79e7434fb6dc31.tar.gz
focaccia-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.c51
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;