Add a standard vga variant which doesn't occupy any legacy
ressources and thus can easily be used as secondary (or legacy-free)
graphics adapter.  Programming must be done using the MMIO bar.

Signed-off-by: Gerd Hoffmann <kra...@redhat.com>
---
 docs/specs/standard-vga.txt | 13 +++++++---
 hw/display/vga-pci.c        | 62 +++++++++++++++++++++++++++++++++++++++++++++
 hw/display/vga.c            |  4 +++
 3 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/docs/specs/standard-vga.txt b/docs/specs/standard-vga.txt
index 8a4c1e9..f82773e 100644
--- a/docs/specs/standard-vga.txt
+++ b/docs/specs/standard-vga.txt
@@ -5,9 +5,10 @@ QEMU Standard VGA
 Exists in two variants, for isa and pci.
 
 command line switches:
-    -vga std            [ picks isa for -M isapc, otherwise pci ]
-    -device VGA         [ pci variant ]
-    -device isa-vga     [ isa variant ]
+    -vga std               [ picks isa for -M isapc, otherwise pci ]
+    -device VGA            [ pci variant ]
+    -device isa-vga        [ isa variant ]
+    -device secondary-vga  [ legacy-free pci variant ]
 
 
 PCI spec
@@ -31,9 +32,15 @@ PCI ROM Region:
    Holds the vgabios (qemu 0.14+).
 
 
+The legacy-free variant has no ROM and has PCI_CLASS_DISPLAY_OTHER
+instead of PCI_CLASS_DISPLAY_VGA.
+
+
 IO ports used
 -------------
 
+Doesn't apply to the legacy-free pci variant, use the MMIO bar instead.
+
 03c0 - 03df : standard vga ports
 01ce        : bochs vbe interface index port
 01cf        : bochs vbe interface data port (x86 only)
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index dee180f..38a0fca 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -179,12 +179,52 @@ static int pci_std_vga_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_secondary_vga_initfn(PCIDevice *dev)
+{
+    PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
+    VGACommonState *s = &d->vga;
+
+    /* vga + console init */
+    vga_common_init(s, OBJECT(dev), false);
+    s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s);
+
+    /* mmio bar */
+    memory_region_init(&d->mmio, OBJECT(dev), "vga.mmio", 4096);
+    memory_region_init_io(&d->ioport, OBJECT(dev), &pci_vga_ioport_ops, d,
+                          "vga ioports remapped", PCI_VGA_IOPORT_SIZE);
+    memory_region_init_io(&d->bochs, OBJECT(dev), &pci_vga_bochs_ops, d,
+                          "bochs dispi interface", PCI_VGA_BOCHS_SIZE);
+
+    memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET,
+                                &d->ioport);
+    memory_region_add_subregion(&d->mmio, PCI_VGA_BOCHS_OFFSET,
+                                &d->bochs);
+
+    pci_register_bar(&d->dev, 0, (PCI_BASE_ADDRESS_MEM_PREFETCH |
+                                  PCI_BASE_ADDRESS_MEM_TYPE_64), &s->vram);
+    pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+
+    return 0;
+}
+
+static void pci_secondary_vga_reset(DeviceState *dev)
+{
+    PCIVGAState *d = DO_UPCAST(PCIVGAState, dev.qdev, dev);
+
+    vga_common_reset(&d->vga);
+}
+
 static Property vga_pci_properties[] = {
     DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
     DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, 
true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static Property secondary_pci_properties[] = {
+    DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void vga_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -201,6 +241,20 @@ static void vga_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
 }
 
+static void secondary_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_secondary_vga_initfn;
+    k->vendor_id = PCI_VENDOR_ID_QEMU;
+    k->device_id = PCI_DEVICE_ID_QEMU_VGA;
+    k->class_id = PCI_CLASS_DISPLAY_OTHER;
+    dc->vmsd = &vmstate_vga_pci;
+    dc->props = secondary_pci_properties;
+    dc->reset = pci_secondary_vga_reset;
+}
+
 static const TypeInfo vga_info = {
     .name          = "VGA",
     .parent        = TYPE_PCI_DEVICE,
@@ -208,9 +262,17 @@ static const TypeInfo vga_info = {
     .class_init    = vga_class_init,
 };
 
+static const TypeInfo secondary_info = {
+    .name          = "secondary-vga",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIVGAState),
+    .class_init    = secondary_class_init,
+};
+
 static void vga_register_types(void)
 {
     type_register_static(&vga_info);
+    type_register_static(&secondary_info);
 }
 
 type_init(vga_register_types)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index fea30e5..8eb4dc4 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -171,6 +171,10 @@ static void vga_update_memory_access(VGACommonState *s)
     MemoryRegion *region, *old_region = s->chain4_alias;
     hwaddr base, offset, size;
 
+    if (s->legacy_address_space == NULL) {
+        return;
+    }
+
     s->chain4_alias = NULL;
 
     if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
-- 
1.8.3.1


Reply via email to