qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 4/4] virtio-vga: v1


From: Gerd Hoffmann
Subject: [Qemu-devel] [PATCH 4/4] virtio-vga: v1
Date: Wed, 12 Mar 2014 13:55:14 +0100

From: Dave Airlie <address@hidden>

This is a virtio-vga device built on top of the virtio-gpu device.

Signed-off-by: Dave Airlie <address@hidden>

changes by kraxel:
 * adapt to changes in master.
 * codestyle cleanups.

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 Makefile                           |   2 +-
 default-configs/x86_64-softmmu.mak |   1 +
 hw/display/Makefile.objs           |   1 +
 hw/display/virtio-vga.c            | 169 +++++++++++++++++++++++++++++++++++++
 hw/pci/pci.c                       |   2 +
 include/sysemu/sysemu.h            |   2 +-
 pc-bios/vgabios-virtio.bin         | Bin 0 -> 40448 bytes
 roms/Makefile                      |   2 +-
 roms/config.vga.virtio             |   6 ++
 vl.c                               |  13 +++
 10 files changed, 195 insertions(+), 3 deletions(-)
 create mode 100644 hw/display/virtio-vga.c
 create mode 100644 pc-bios/vgabios-virtio.bin
 create mode 100644 roms/config.vga.virtio

diff --git a/Makefile b/Makefile
index bd9cd4f..d971e32 100644
--- a/Makefile
+++ b/Makefile
@@ -318,7 +318,7 @@ bepo    cz
 
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
-vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
+vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \
 acpi-dsdt.aml q35-acpi-dsdt.aml \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin 
QEMU,cgthree.bin \
 pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
diff --git a/default-configs/x86_64-softmmu.mak 
b/default-configs/x86_64-softmmu.mak
index 1a00b78..22d8587 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_VGA_ISA=y
 CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
 CONFIG_VIRTIO_GPU=y
+CONFIG_VIRTIO_VGA=y
 CONFIG_VMMOUSE=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 6574830..6d5b792 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -36,3 +36,4 @@ common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
 
 obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o
 obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-pci.o
+obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
new file mode 100644
index 0000000..ab6f899
--- /dev/null
+++ b/hw/display/virtio-vga.c
@@ -0,0 +1,169 @@
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "ui/console.h"
+#include "vga_int.h"
+#include "hw/virtio/virtio-pci.h"
+
+/*
+ * virtio-vga: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_VGA "virtio-vga"
+#define VIRTIO_VGA(obj) \
+        OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA)
+
+typedef struct VirtIOVGA {
+    VirtIOPCIProxy parent_obj;
+    VirtIOGPU      vdev;
+    VGACommonState vga;
+} VirtIOVGA;
+
+static void virtio_vga_invalidate_display(void *opaque)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        virtio_gpu_ops.invalidate(&vvga->vdev);
+    } else {
+        vvga->vga.hw_ops->invalidate(&vvga->vga);
+    }
+}
+
+static void virtio_vga_update_display(void *opaque)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        virtio_gpu_ops.gfx_update(&vvga->vdev);
+    } else {
+        vvga->vga.hw_ops->gfx_update(&vvga->vga);
+    }
+}
+
+static void virtio_vga_text_update(void *opaque, console_ch_t *chardata)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        if (virtio_gpu_ops.text_update) {
+            virtio_gpu_ops.text_update(&vvga->vdev, chardata);
+        }
+    } else {
+        if (vvga->vga.hw_ops->text_update) {
+            vvga->vga.hw_ops->text_update(&vvga->vga, chardata);
+        }
+    }
+}
+
+static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        if (virtio_gpu_ops.ui_info) {
+            return virtio_gpu_ops.ui_info(&vvga->vdev, idx, info);
+        }
+    } else {
+        if (vvga->vga.hw_ops->ui_info) {
+            return vvga->vga.hw_ops->ui_info(&vvga->vga, idx, info);
+        }
+    }
+    return -1;
+}
+
+static const GraphicHwOps virtio_vga_ops = {
+    .invalidate = virtio_vga_invalidate_display,
+    .gfx_update = virtio_vga_update_display,
+    .text_update = virtio_vga_text_update,
+    .ui_info = virtio_vga_ui_info,
+};
+
+/* VGA device wrapper around PCI device around virtio GPU */
+static int virtio_vga_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
+    VirtIOGPU *g = &vvga->vdev;
+    VGACommonState *vga = &vvga->vga;
+    int i;
+
+    qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
+    if (qdev_init(DEVICE(g)) < 0) {
+        return -1;
+    }
+
+    vga_common_init(vga, OBJECT(vpci_dev), false);
+    vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev),
+             pci_address_space_io(&vpci_dev->pci_dev), true);
+
+    for (i = 0; i < g->conf.max_outputs; i++) {
+        if (i == 0) {
+            g->con[i] = graphic_console_init(DEVICE(g), i, &virtio_vga_ops,
+                                             vvga);
+            vga->con = g->con[i];
+        } else {
+            g->con[i] = graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
+            dpy_gfx_replace_surface(g->con[i], NULL);
+        }
+    }
+
+    pci_register_bar(&vpci_dev->pci_dev, 2,
+                     PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
+
+    return 0;
+}
+
+static void virtio_vga_reset(DeviceState *dev)
+{
+    VirtIOVGA *vvga = VIRTIO_VGA(dev);
+    vvga->vdev.enable = 0;
+
+    vga_dirty_log_start(&vvga->vga);
+}
+
+static Property virtio_vga_properties[] = {
+    DEFINE_VIRTIO_GPU_PROPERTIES(VirtIOVGA, vdev.conf),
+    DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_UINT32("vgamem_mb", VirtIOVGA, vga.vram_size_mb, 16),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_vga_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->props = virtio_vga_properties;
+    dc->reset = virtio_vga_reset;
+    dc->hotpluggable = false;
+
+    k->init = virtio_vga_init;
+    pcidev_k->romfile = "vgabios-virtio.bin";
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_GPU;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA;
+}
+
+static void virtio_vga_inst_initfn(Object *obj)
+{
+    VirtIOVGA *dev = VIRTIO_VGA(obj);
+    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GPU);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static TypeInfo virtio_vga_info = {
+    .name          = TYPE_VIRTIO_VGA,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(struct VirtIOVGA),
+    .instance_init = virtio_vga_inst_initfn,
+    .class_init    = virtio_vga_class_init,
+};
+
+static void virtio_vga_register_types(void)
+{
+    type_register_static(&virtio_vga_info);
+}
+
+type_init(virtio_vga_register_types)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 4e0701d..971b3ba 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1647,6 +1647,8 @@ PCIDevice *pci_vga_init(PCIBus *bus)
         return pci_create_simple(bus, -1, "VGA");
     case VGA_VMWARE:
         return pci_create_simple(bus, -1, "vmware-svga");
+    case VGA_VIRTIO:
+        return pci_create_simple(bus, -1, "virtio-vga");
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index b90df9a..35358b8 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -104,7 +104,7 @@ extern int autostart;
 
 typedef enum {
     VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
-    VGA_TCX, VGA_CG3,
+    VGA_TCX, VGA_CG3, VGA_VIRTIO,
 } VGAInterfaceType;
 
 extern int vga_interface_type;
diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin
new file mode 100644
index 
0000000000000000000000000000000000000000..2b70d272f2704e7839712a61613844321b93b465
GIT binary patch
literal 40448
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
zVS1$N1mB6S3}l-&$}kI)X}Az_EHhn11s7vB6Wl1H)HavPBXv-6Xmp7adWV=3ayFO>
zKA;Ww<%^vVv{A!3(Db0HB7+=Uu%k)Ii(address@hidden&y0OD
z%4VYMpuzLW<)ojY>b>3-UBG3aO)Ic!0m{Ocq)FbJ^xp^-J{)`)^2X>QPfq%BlvDnk
zq5`ijLvEd}Jw%?oJG!_JsCkNWB+sr_UvKvCo;#Pp!;~$ctOgTIjmoxdt4*9yHM*pf
zWV%*O0m{AlYNolCTVRinCM)M4JXj6g5|MWptT~|cB}8M6OZFXhVsk}lv9b&ymW0Pc
zWkY;MrYk?Pm>hDRn}Fm{$eBalB)njZp<dkFl}xHWz_WyJuVVtCxhtcW!D}HmQ^^cv
za1P<+uq6adaygaEphOiUCfNs<OBB0sq0guUOyz}B^NeO-0&pVp>Z|OLQYpEixHyRq
z9wvipDr+{lk-VsR#qMg3&*rYprK*2EUebc|N_Cp(f~mLE8pUh!;sKQ72Y~YFjWU{o
z<l54e>4ue(T3(address@hidden>3&M)V9R$)?kT-0AI$vHkTV@;z1
zHDG5^jV%Q|address@hidden@5KXi$iXX{13Vmm?~<94$l@)address@hidden
address@hidden;Flb4NZusNA%O>>address@hidden@4<
z5|!m-hKLNmJYr24N%Hq`Nn4<b)GS8FqR>!Uu5jrp4_}=wxz?-I15W$E!S2_)yLnE-
address@hidden;`c*oaAZ5a&n>0=lVc76Q9rtL+6p!O&B$<JNcAWE*9yAys%7QLDVe~!Dwxf
zWt_wO<6JV?)qOZvb99f#zgP&address@hidden|gBoL76emYsUeBVBu#Q)8>mKYElP
address@hidden(9DkWp?sLDqD+VZ-z{NQ$rZupTXga1IWJstCH9$fk$!W?n6KxNu
zmgLRMnP0j15|address@hidden@|sAfb4X!HLZ1A&VrU2QIQq4_{=N
z9>nPN6csL%0SuB{D8m{gnHOuB9^&XURgYxW2zO)address@hidden@|address@hidden
zZjpq4h~$+7;bNOEofiqxqa}IQV<vf5l~e`3H6A^Dm|address@hidden
zT{5VWc0SVu!-0vUltcztG^6>V<pE1hQs!i^B?o;QMfwy8aFMcf%GY3H10T1K%cjB`
zTTHl;h#rb@&f!8l_8tN<&XoqS?Nd_|ER~pSGhnr34h+g)&MKEyDjvCeWO5`gNTEv}
zm9s={JS;F+djFun*u&JdSP$l?0aHLHn>XBIBdZb=;>jS70Ea2iGgi>eFg(whCtNdM
zI*AXu>k;4%*(ssNfLWCn!WstB!XfvF6;*2}NGlh1T+P8Cfpo(swMp(FQ<`byLP8lY
z=7K_$>rtT!3$eCJb<m|LBSRxJ6f!n6f<qGLknr#nwxCb-<O0O0i!+O->W<)$7*TEj
zphZ1Qq#bG*Cvu>O^`?fju+|bOLWA^RF-K3yQ$~-ZAX0uxRdOLCIJN|h2)gvWZG9Xu
address@hidden)f__t!5l_Hm@<wu1(Jdz$(pV`vUxq0RBjXe
z?HXC2J~3<fQURsF4B{&nCmMU|dcFLxl19~3AwRSv1iiX7z6?b>JC7Xc?9|PK9$_j2
zg8}8pE~y(T6=k}Vn=AA<Q+J3}q-m7vv8IlXXp;!ylKhad$vG*~^+v>Lgq(`=9Q(2-
zx$ZK1WQp|tkpVI$tK9Nu9HTu%pT_udgQftKqa9O#DC0MpW708GQK%7y$|nRU#zO+W
zWF*R){^q<9KCr+2dY2xKva`tXs4};DM5=Ed=`pE3-;address@hidden@XMinrn}qMqxN{
z$#UJX)6KbV-1YHDgLl||gFjWC7o+O!p&U`F%Wwd*M;?(=RxL9aPI)!U_L&address@hidden
zKXN3i2U}c(HBILi<>V9VAswEm?V*Kbf2XvKLXTQi*eZlIa20yw%AqTdrsQLoPf#2t
ze#KrW#WiZa8Zm5C^#^n)iq%6^dP2f+td7s+m;}0fb;mvzByu#H7tiYQg=$u?K$SdQ
zDyFqYwfu02yCjiw@&fQ!7B>0F5iX_=>E}m{yd2_Oe`L8e!X^InDNT=L4E+EVvhl`7
zpijoRra)Il876tqkQ?KV`pA+382nHn6u`(!{jtWphNGlMy(;V_!zbfjrC)mFt3qGi
zB{nE?f`difoaJ_vWB`mOC>H*qd+2X&address@hidden|S>XO6yr
z88Ej;^vroY6Sn9F1ZT+;zElaRKV3P4Mx8fB$7l$)RgaHz0kRMq7f#uB_~=$D&&9|x
zNLKvP2r2zxesg)rZ!T}d%BufV&QYi?57Z}YBVtBx<t6ENsZzZ?tbLuBeVzKosxiG(
z;4Da)<TDXwALgz3&gdo>x%W7qi=H`rW&xPTi^kh5KN666zEIx6zY#}cVED0wVQ{%U
zYb>1?O_K$pcsi-~k1Np{n&g!H$hdIHBsM_lQGCq{Uw3)R08;address@hidden@@
z0h%SaCSO?(uZ20frnEJ}zWKZ62%FL%J=`^50UGhM5q<W{AWg;BaKSA3q4*<2+*F5!
zV2!%*K+t7)address@hidden(7d}|C2e5Q*Jg<;?;address@hidden
zqw(A$M7=p{L{5(k4f>2?jmoLMK~I$%_$&`2HXj<D8#@&SzFvQ5|CC(yTcyq_<5}Z$
z{ZS<sDLiYej{N|g5F_OtVd~8e9WO)P6eF20Mc)8fBllCMtg$-|;LA&AU*0KxHv)Ki
z;&!+jCJ2U|E+d9da+V+*Y8t_2ULenpN{vugMNGM19xIaUrlMyJ=*dFx=A{bhIg3ZC
zdQdO)s9yKiK?R{aJ!4guHMGZ*SdQ(D;address@hidden(h!jJO`=
zTc6PC<A+FJ5B1r9HwXL1vs-R%n0Oy>V`3?m<l8`$(W8Dm+vPHA+>ZynhlfP|SWZ7M
z_}_QH(cam&@1UdI*|+Z*N4veR<C|Bl)Sd}fS9j`fTa{nGu6#_9n3|{(4<7FDiMGON
zFJ{LCM7*$Lw`ljZ6n5M%+G}uY5$$Jji;MOfaa%9iN3|4|address@hidden<
zi-a~_JiS<GW5m<DgjOh?eoAOI(fPpP2b1wLbDlqQD40yY`~5SAuD>xM932AhJKdJB
zjqeyO;_v^;*LidNk8R;`Ej_`vdVlL|address@hidden;iMK-<~Q*Sup9TjEBdi7Rhvw
z(sN`wK<Q~SMct`T;address@hidden(>Lb*rRirq(y14Fe+BA3P;U$SsI`c8%jlg4
zoxMMCW*dv!!X63xyoX?qJNK?BUb%OTZ>3RCJ!a=YS8v=oCy6HM!$TiF`Y7(L(;5HD
address@hidden<TuML=ssMX$=>address@hidden<address@hidden|DJn7iGW?YWlulT7S
address@hidden@*FbG%PyD+K~&address@hidden@<gzS58HD
zIuds3JvA)lz{7g&B~*AVHJWYoX!p+~9_Km0Qtul=Cn0M|ve`y=wsE3jIeYoegT=ib
zn?z8+J+q0%8DRmsg9QA875Fy{{FRV2wefQZ=V{>35b2GAFKSWi2XayGV~T>N1u?8&
z)address@hidden)FVtE6m<CZYa*g+(address@hidden)8^e3;?GZKXWG5HR%d5=
zyt`}+Dd*2C7`}wzH!=h`s8z?Gf5o5oacOI|cYwr^3TYS5O)X`a>C!qe7y2qE$vB=Q
zN?^a4TU~7e7pFWk1NF(76YBTRwACN!{kBb)xmj~Z(address@hidden|l*W
zv%Rap-?-Ejd)IhYf{6C!m5_QW2u#NJY5f4WQe`>74;B!B*b?>6gQZvS_l9J+ln55u
zv{zT{PI`CI;EYRclueWFYggTds=a$K!jc;wL+`yEN|*Xe9q3_T>~jSCoMa1(lah16
z*S|ocwKO4YB(#O<eucV!5|-w4sA%hjhNW>W+`Zsy3;tz6YQX{g$)6(&-dvFSRm!C*
zVd!VUlCM})Dz+|address@hidden<address@hidden@o990?{~zWboWE`1Tk~xdr4`#2
zUR`lr#h$BQy?Wb1^H0%&OBT#p0Yy5S`8-+98(PE8@>okayYpa5d-~Sh$$B>oh_>Tq
zvY*cK?JZ$gCMOhJyQ;Ffx+R=x4QE2x250=l=R1)Mz7_9mz5na>address@hidden&#7KXkne
z1KN8359}xjpEkjEU?pf>address@hidden;pHyOyTf%*b76tg01iX`oE5QGf
zfRnA^ljZJRN$>7!p(fzwhYo6gN9Po@<s#eB<%no66Ec~_=aA{5Odf7w>Y|R>Me#L*
zsTmz7`F>address@hidden>phQ-N&VTP^j0SOt0hb5BNJqrn|rQdr+exEf-3$d=K4P81Aq8
zTwAz5e&A4#?IlNe5Yj<$B=J0WSwOrPg;hgJORc3ti_b4c<<zCrFQU~)Sv~WHIr9o-
z&`K4!#cdH@;kobAS(2PRWN#P)address@hidden&2_2
zW$SERb}{vaaB7FNGhQ?%6D1fhDqNv+M42Ue<{&axQ3fwDM-tB<cPZy=0=%XwsdYjb
address@hidden<h(%Oi=yfizKSvS*K`x%G8$^fO3#f@(6KX<`bD0f%Di9
zGH&!GZ<y^NTSGzONk__&c*PM9znvH>BH6~bwJlUR*C>G^Bez+EHrv8)S4Ff>4r$cS
zjaoX~x@;7&cmOP(522MrK*{$c=V<g^4AIoh(address@hidden<H{=~Q;B
zQ~U8kT4Z;address@hidden<yO|9di0i;address@hidden|I#Cmx$QNv=$Pr
z*6?|KC`+k^G(L&zL4_>address@hidden(czQh?_PFk~>ZTOElTRQY#gg|`!H72s<address@hidden
z0&J3iQ;FRQ&?re}JvGFMZj-JfXyPnzbfYwnA-YAfBL{m)Rdmn<MsTA_t0L_nNXJ`O
ztxSAdK}Io-NJbLhRgg2ZenHxa^$PHU4u~qi&j~PO;9y!Yvc-u);address@hidden(
z(mHJbne2dD)cp}fTEIaHGsJ{RYR<7ghO?b;@J)XE!1nP^H1oF)Y!hW|;ZwbpLczUH
zcx>?JpD4DK^<J$5C*^>tX$o<g2{tz6o#htwKbz$e_1&}VqW%aiELfLz9vq<cr;^tn
zS9w`W7(K>1)N(MGw1-`>S70I1*~WCDMhPW(HI0uh`g-KBf}G6_DgolOe4Q;v-|C}n
z;mjh;>NTxlSIE8PR#NuB7EA}UQH2{8518(~(SiC264tgnbEX%|i*_AYN|i81RSrnd
zp)l}ls9k>rw?CLDA{#NNRT4i;8IykylmBu8Bu2~93uP&-V6xQ5?CYYzy6OxSHu55z
zZIpsJ)Kd^qqWD*|<x1SCa`#Znn2D&fAbj4tJ0Xn8bBE59J{J}d00M}IA$=FTf;I>u
address@hidden<|~1_HY&h;|address@hidden
z6jSd`YfGsWD59hcVyCJ91SD%g7#C8e6&TciD)kXSsm2XApd3TVY7JwM(GH>knlkKp
zX0(5$tVu+Mj{GGt0xYidkisHQ%n;oQg#jNvqkWMu41I*xVhG)^M;^j&3BT7Geh<8A
zW9O041LnKBkF<A92Ht#nB}*xyRc4vBcdecZO}353sQhvs^))<address@hidden
z{bza)address@hidden>80_~ZRXXIqrrqn
zs^@)_$G{i^NDBN#0w(a?D5TyslxYQquD~lK0MsLfX1;$Fn1rB}Y%V^JI)=ChIj$o0
z!Ym-=q9nq>address@hidden>W}#9vLZ}D6mBmwDP}(address@hidden|C
address@hidden|L69teu(f=!=Z}cE-5I6Mzjaqw<address@hidden)AB
zr{-{fz=Vt}QHNN>!bpABS=5dpQlj+|address@hidden<Z8C2;$74
zrCEf%--d^9j*aOpx-cQdLz;address@hidden>?3wl<RS~4P4
zDS}~%Il?qh3HXde!!l6b`<7=7iG1MT<hq)nuAWadK)&453hT&address@hidden)q-H
zotpI__4FQTV+q|ls5=d&address@hidden)nSj|-Dk-j?U*w(W;address@hidden|p
zieY(fBpBO%AMDpyW1?Onsrp!<DWWMPXS^lsVGUgv9w5K~0L46&fzen%f`bKs2G0l=
z#f}O&address@hidden&k;zCYxMPI97DRI^Knz<5q)C<93^h1z-*qhEMH{zT2>j+LseX
zL9PN0uTg+v{yimZXL<|ZEoU1cMGG6`^Zo*REbiV;+G_~eyt|J=waKD{Pxl_czS3zq
zK|sl9v91tZ1uIZeDD;address@hidden>N1??UI7gilyc-)jlHeCA4b<
zT&(4A7ntwU-ko!^y|1Hh$Wq^)mEDxRTNpmQ^*^Cg4cJdJcWMS~%Te*4)Tu9mI3~61
address@hidden>%J%-o!Lo)K!p4MUaa)Fc3YbdEK(address@hidden<0KGD
z#E>9OyEjkM?#k1&n++5GSG1R?>zy*$Z0)6fj1WUj#kQo|Fx>NaKk`Cd6I<mFp^vF8
zhKhh(o+4htYK{_$pR$ec-$*av6QCnx3jX5k&V!!R^!#!&RmR*t0L&qpvt?)RgWyE!
zO{$4!N1obz7z-K^&SL>BNgXjUn?3`~4;<&_Z0|eyTRx7KFbq4*%dOI2Y?i}#Pu?)z
znm3Hs4mWT#h-tNCf8ZeAhOKCKZ#7s-V^gJ+g?^}~B}_{Yd6;k)&>}YP$g^e}^Pe`d
zmw)address@hidden|6*jn_mM|-(?=NDR7q+a?QEB2XxDmenm#|DR;wVq|BGkB``>x+U1QbT
z^GROy$RQ(DZ<|address@hidden(<m`oEQEsyzo=H7yi_H(address@hidden)ONt2*#r~
znD4wJiiDOZBX^!{K0E>Iq6UI;QFDa*C_W;89W0uO(Mt5I8E6Mnfn$^uGOm;`8~{`(
zPWd~wPm(*6+o$o)WXE<d-HT=x*S|H>UazJ4c-<x4CD$>}cXqSy3_Vo7GdN=;c>H#+
z+{bArE)2W&address@hidden(^8Vj%hM?|`<1BeN!
zG?Thl8R$ez#DDklfb?HwZ0~VP+Ovrk?f=0U*Z%P`WY|v0_>wnKFAARrH<O4hFIzf^
z`xtOtDWBZ);Mxxo1T9vn-D|h^zHQ_nAx}3rQQrF^*?liK67K9t*x{4t(8-+0rF2=8
zPgTK*fElpH94g+0JRwNlfab^uQur~<0lI%kdnzKxaVH4?!k*+Pm>YP#fV9V00LA2Z
z{1|eRVjjnxha>x)>F7M{T8dpN_PsNyO~XrLnO-}9ji4Ff3|3yUTIJYwZ(IKE%RSZA
zbHiz(HFc!&A};4u;*cg+OG9pTt*quyPKX+uT?Niua3Xp;^0|JGc9Vy4EmyF-G5oa7
z^+k}p<oZw#^X(YQcVJ|U58&Kcx5vu)address@hidden>xGO0ueDpH-vR{>i7a+8Xl
zb%0BF9yI79Yr&4ZxghaL8+h#Hr1%Wo(!-A{)EB!kSlVD^U|9O?7}{45bkgMb0iKDX
address@hidden;2g^NlC%M`_J{+}^vGO(address@hidden
zr-9xO<2gVuHl8rhJVn$q8ru2Tz|1S-N&Uj$4>g`>*=jsl?s79w#;&KbjYZi;e8NUr
z8X=?F!w;3;!$6=2LpYpci1D}7Yh4C!VvsG_5V$=B?}FkhcC*OeVtXca0iWo7L|Z;c
z&d!}|;address@hidden@>address@hidden)WlQ?to!$AHQdh6aPP%u{j<ulwS|k|2^THOX6xZO
z!No;b=Dlypa3g*zq+uHI&t3c>address@hidden
address@hidden@XOx+(otW<address@hidden)VpF?TYXh$WaW)F?R(8}
zVqenHF8W#ymwUhMuD3hgeLu9t-t+<address@hidden({f-mmC*6mU>&xtqopm-GZx8gXzU}r^
zMs>address@hidden(5tOvA>%qz`{zQE8e3D(address@hidden
address@hidden&address@hidden@O8z`4zcsR=Ad4x&;mUEwxg8;dP
zI1jyF874HLumFmwoB>!k_aW_&!E$P{wanU`BHd*eV3%QlImHURHvoRvS`Ue79cV2K
z8(address@hidden;4=LV>I&jQ-u$-i-h)Q9E{RK${7EXB-W*Qb0P{1Qx
zNkNz5XxLZwKF+0Z!~|CJ%u5%A&&j2R*KXy$>wWue83dd9lrh{-BJU(M;URZ~-8|6d
address@hidden@bD!L9uA!+bNNer*8jv<&-=AE%CPnt8oG=q=QQ+&ssAAjy~}2>Y$L*L
address@hidden;address@hidden<wWq;sRRTJWlBj2Z)lcpMN_Q8Mwbvc5s4A7~c>&
zOB3t)address@hidden&w1*6w2q4%BOSV9znroQd1)-*fi>eQn1rX!N@<NHTHKe
zYvmM;r!M5KO8t>YW)vHtEH?!9(address@hidden;a(o=
z`|(--Wa<re1p2jIgda>o7+8Mc8uV-51SI!7=M)&T>~dDg23&?-%vLQb&*;k14_PPg
address@hidden;>O&(c{+%#tPx=P1$-!*<tfAqS%PbU_Uj3<5|?(Oz$aJ6yE9Y
zJ%$wR)366ba}jAe2B1yPVhdvL8a>h_xc1^(!?MJNwY(4w{kZq5pf|+9fmi0;eIL9f
z%+inTmy!1~{2E<address@hidden@v!h7hCOy{#bgVcyzf
zr#_;$_V%AX)LZ*E>@IxRx}CakW}$bNm-W`epO^9H1(address@hidden
zejXESuzPnuFQr4XML+Sx<3`~I#_hU~IdCHl#f-^3?c8)CRVo|roFNFg&N#|}5GX?B
z+N$F?&X>A$WL$*hj5wPRC7&F#fMM+QBc33mCsQ)UL7I2$S(|Nd&}6|=aCsPcWyhVO
zwea?qXIJ6~a_gnBw_+XF1K{rI_!P3Ymvx3jgFSTzPU+ZF4OkH2w?p+Dz26l0M+6T1
ziv;`|0!Q!fL}(OlJtE}8ZL%#i4!4=M(0JTFV+&2dEp7`<!tI;3kRP|FZJ`TrJ75b<
z#;wcN89P_9wIrfDSS^S9S_b;abz0TA^2cMfp6u=HK*e7s5A26R`cId%7WOSAH_O-X
zr}nXZl+AftI;nP_^vce_?MlAsklq%d!6&0er<xlj|E=X&-OJ<VBh>address@hidden
zFM|Q;2r8HFl9ocn$8o*xSZ);sIzV>=Z`${q1Kr#Aykk|QrKhh&>jM#Vlif=$T746`
z`MiUBm;1QBLH8qv^bGxK7*oDIdA!g)Kz?WHf{5N`N#CmSSc4;Z+#WmbRRSef^rn5!
z5)Z3d4x*hCdwL=#TAn%4vR~(d3l$e9sBgIsgNvK?brA`wLdg>?oieE$WGVEP&Sc6E
zKnY8v<yo-O-)RF^C+#|)ENJEO(($XvBsx4N5529P1bwB0U;{WOjPs+3XMu1n0r|+@
address@hidden;PeHY&Tx7Rr|Fq4o?De-=Li!Iw&1D1l}XsLr#{2`Nm#wv<t>N_I-?QCsf_U8
zqDs-|N>mEus7X5W`0I&iQbwZOz=0w89}USrPWiU56Dt*N1Go*~wlM7S-dB<3BZ3<y
zR#zKm&$bXcO-sB;address@hidden(p#J&)8{~+iEW7$sCFUDEK3kZUi2-WRKlb
z)N-($d}$P67p}l}vUAR_&%7s(1LaO5d~X6Z7tSO`(bK$)cAD~d&Rm6)o)bu-XE;!#
z$AM?cA(qi}9)+Q2V5cNvlIj2r7QknmnY#Z7fGI!ME;ye>eXL~#=`7ARPzh%v#)+a8
address@hidden&{zx*UE=Svxw0#mKkNbamsiP+5H!+XPEV-{)fQ3}ZxhPR#CRvf
address@hidden|+--k_)7`rS_l~C*YDY&m82a&+%16JGeG#wC$7-!(VMYx9dJD}Z4$0o|r
zH!`-get?PMa_qHn9=lp9j=~8WC{e1KUppXP2IWRBdEPi|address@hidden)
z>okW(address@hidden)address@hidden&fkUhxY#PuyQ0yAQ8=TCMc)Ny}
zIzWB6>?MA<f_#oCI&jpsW?)C>_DL&oG!5)Y#`?!u7{iI!x}R$66l0^PmezXS!dCgm
address@hidden
z!2B3OWA2>8aOcyxn`YteS-c-&8b=b>&$X)z?odm+U2#WmI}=xUO7kVWH2_6(_Aa$0
zng#g^+Mhtkc(&n1pIwP<vgEg_gwI{QkBqB#jxFJlCzJP?s~x7oM6oP+%v|kht~N-A
z6EV{K{N#HC!s8OWI>3~_&M3b%qqImAua45hC{LPE)=QM}I?BzA@;address@hidden
zQ=3ez1SG~Z9mB^MpD|%%e8g<bpwUP9)F)|address@hidden|Alr>address@hidden
zjSY^!Nd3mJO%13j{cr?68SNj4l3_Yl8HIR<BBR|;h1AGYI%50a;ov)XldIJmd&AqY
z7B72sIK-kS9S!!M+E$fyc1~S+Q_BJQCK#TT(>address@hidden@KkQ!~o9dwj9C
zPQ|)MHI$TZQmLZylb#r--FQEY-xX`QG%;@6YB*_3GWG{s@(+$2;qo)?ms$!H2HNa|
zrx1J3_R^cYSe%C^bimQa#YX+uySA79V4`r|address@hidden|pY34^s3hfe9N-rhBXcv8q7
z=R?1RaPTM#f#NuXfjHsPhCO)oz)(J+hL&SZk$x+s?BQa5zLtS-6_x8>#c-rn;3X88
address@hidden(ivi=;CY<GV1Y#2`rBBLIH#TBmoXNkIr1+$BL|gPHgnFi3&TnC!Q3T)M
zg^5#*zVaJ1K;address@hidden&NaBY9Zz;T;ftbM^o4j}h
z$xSm!TUQ)EL5hleRTV>SBFI!cfw&%jIGBx+0;k}jN5-Itj`OQSrBrm0EZRmz`dR2h
z$nbjXE|?~Z{|address@hidden|1LSCi{WR(address@hidden;<=<address@hidden
zy-!L=V-7M?Le^0=uuj$HNYITrq`4AONk};address@hidden
address@hidden&address@hidden)R)aN)FXXK^r2S+w7I)NEBQr+!59tAN7;z;+L}
z>)jQ#^MU;R9`Z&|8}`qo?WEf19n=u{LG1}k>3UNspJ&`<DGr;9$<<wtVt%>fbBu?@
address@hidden>jwIzX7?zLTeCjPU?&xAVfz~S75#{%jKx*<d->|mO5RgIuI24K=N9IH$0vp
zhnrp$=>>|c`uu2fzuQbzd3d-rlE6=?2G;1Ri1t-Wl~txHrq=LI23jM2tJx901C?6C
z1LXnoGjVp5UT;~;T<k|address@hidden<address@hidden)^t6upr$P-O1VzM`D`Ox)o>
z`!nd38ts44k!ZLfA_d;2gDudzhlSoWEHq?-lEOi)y}LHsbz`9QkAhHhS~tdoZn&&}
zBpjV3hmJv<address@hidden&
z(%=8M$V%pF9f`=aC^8whrKt&K9R1CN*Q_{yLe`iF`nwFz6OJyM<2r^MMN+-l7;@90
z^}jQtC(P&;)u?;kI39ktxyBxI4dcw`Ttdl-?Rp)address@hidden
z`F5`tn!1`sCO5{)$NQNX<25q|sU98M+x4%4BkSK3ny1L$>address@hidden(
zwG`iGDkkef1lj=Oa6Xf|gyZOSmMWK+s+a^X9Cg3WO+K3i$*rvY&Vz^vmEr!bosEGT
zv}ql};!2kLCoZ&&I13;SD%=GHf;uK`=astc)Cf(@^UajT2(address@hidden;~Jg6Jb
ze>T;<(p>i|rn>SSx3u;U!KASYf!?CAqW%&v0rx{&XQFeWK=J^u2^RKKCPF4AU{imV
z=!SqxT-DX(*y+GJ#&6W6>2*{XXAj<`g;5*i_udMKh|b0U(I+vT&9a!9E$zJ~O9u+D
zrjroY$Wq#Wr}gVw_>utC1&YGWCj2qNRC1iIXtHg;Uy|e%)address@hidden&8Cs2!$J{
zHX7goqBBy<address@hidden(_6iu&oKQI}!1_K;qmmcBm9sLdKxzDbqS
zpm1B(;)q_I`1*mVx)address@hidden&ZNfAee<iGQ4%H{+7-~MC>jqBYyiGU}V<m9u
address@hidden;H_Wlz)&Y`bv--24y3mkbw2IV5g3hYw7cnjJ^`wt7Dj$xl|{k
zuLU6;DM!Yk<LGOFKOg7!cEygq7MuoPh-_XUoQUzp(%U))u_JYLw%&ingbtckf(|pf
zNj>qZ-}9>47i9zbi$Za84TUnFP)Kb0D`Yq5NV)!ABFU(gV5yE^lA2RusFmQtVKDw+
z<G!kuAdB44F-}ShwG#Zh8N)address@hidden|rgrb8I%+f248KFd<tyP#Sk=?b`#%$cl<}oX
z60`I=^oI2Vlu>m|vW0y=WN<LZ3&ouZ)9~fnvv`I_k8!doJo&-~u6%0KdjAyrg0Qmz
address@hidden<4(W#-7gg0wu)bw
z93Ba*rQiFW1!?LnZOc7GYf_FD&>lRDh%(-le(xXFlzlAxZ<+8{P9>U$+t#>R3(Ib2
zzH*>89TdsI&<T7^%<ZZRIXD=K8}OUjZgHMi&D1FQj!Z@<jc6A;`BDIshh(rb_W8~S
address@hidden;~eOVj~qR~y$$6&7$k3F-YX?SIpmQV$xhvZmvyt`hcXNI9*9nQ;V
address@hidden(JJ<T8NeU#Cgyu1ImXj{|2bSWCdYJjJpS_TJ|
zv2Nqh*5K}Bg9{tmz$Xr9V-N?nPH{SQBVMH?s<g}cE<ZfSnbvr?uPxlSXq4EB_Z<2P
zg77j$K}2)nIj=J{mO%3r=ugxNNDx6~y>address@hidden<2K(?sCe<9gy`8GV&THxWp3Yq`+RQ
zCK%L{9{e6-t;30-Xe8b_=lLHAZIPg3W#f>address@hidden>Q0uTztM<kLPO
address@hidden|AHE7ZOnlFAJx+?w>&JT4)6ZoP^5q~bazsKG3(!K#t^knRSGx|=a
zuzg(=;(wS{3GtZxdZ3s+W`Ee`_SxL{_uT-St{$0=*-bDcZNt*&VH#L1ud-nG$lOpG
zc3asHKGxx#wN-Yv&*`)|M74#6%B&j#bmZ|7a7Y?9x7#T$w4nFMTtNMEY`x5x$489*
z-MNGKusg(MI-dCs49iuJ#|J1d4V&BJ6eSkq9+h)ipu&~M$7A?cn8HbXI2^g}qcYb5
zhUF^E=c7Q<u(?Z|address@hidden;yzJOgn!UU|address@hidden
zYX%pOOv5K>jCO&Byv#IAU~e9cq(kxHceunYU<m&u)Jh|Xu{DEzc{D^p%+7l1Epmy;
z7N!*+ke3BKc4QhpNyEgnnT82GE{{g6Q1RjSy2Mxu)4Dtgt$i7vN2AK6blnRYJ`2-|
zMwQFjmy(fb_#_Pz(address@hidden@XHKP<C{)sM8G+bY5Mp^qZF^>lR_qLobUcXC>8m=$&
z-?_~?HfdxUK1svGv_39G!vyx{)address@hidden;8m=$GW9`cY`80~uobyh1A!TM-=cCBl
zm&address@hidden;address@hidden<x$yHuqE~%(eMae2|Wr
zuTSLBh<OwZ??U2Z7<t4XQ!{w#$TWPChN<I<52j%Pm*vq&address@hidden
address@hidden@D<uuLpVmi312Q+jfQoDKX%wmTHsEvNUv&>h1NxzZiN=y)X|Np&
zjCVmJb!0OiLuf3`qY?9{c^jDO!q^T&gJi0MiI3_$8n8QZ-Ufm$q;zC6A3iIMYx8N8
zC_N2CT*5vq4XmI#Y2qWCN2AK7#>H)O(g>KY9+|GPnP5mR%cCJKQ2G&Q%;|@9Y%j3#
zaa|sbm^0?Af$soU$f^GucGYf=yvK&D``72u5Tg_gZyAk?d15FUu#gt;r$(mXlQc{d
z!%V{j{&XIV*cio!|MJ|}%1$U6u`#+lB>09r8e*KH5m=P7K~|X>bI#3QZrhYk1NJmP
zGW7*m9ww&szK}gNf$z<address@hidden
zzFfj<gNf-8`qG?F1ASo{{;P9*NTzifL;CWid>ZHr(+GU}BhI;Pc{Hj<KUT1d`!doR
zRRxdJJTBYwX!Q6LjS<(V9>adfF2?d`#3m{lBifJHM15?fj_t^!ajK}PU^1<9K71<@
zEJ*&ioEoBI_vO*J+ox#wt8+57jLY3a`m!^RM$ZIABd~e|8`Lww+Lv8<Gy-EDcFDfX
z<MlSbF9FP3a~F5#(P$s9X!vg&p)address@hidden|Sl_vF#2nyhF9YDefx)nuK99GCm^Xb5kt
zko^zeGUCI`v`N>^;FdfZv5AU?e?yKB%edt9LxSUZG{jUzBe0kJ9ept}uX9s#V4~8R
zPoqQ>Rk=vVzC?VOneL$)xL`lb;address@hidden&W&vJaox;^qH3_fK3fqWX%6^+1Pj)v7H
z<Nu)QT_h^{zwT8n{8_gpo7UdFWp<=?eN)A}z%5Izoxb$4z}#T)ioo6V^_v&Wp1tLc
z#yd7{yyNc6H*VT^*T#m+H`U!Wdvo2U4eQs|Z<*bA*By7>address@hidden
zwpihy9=K-R9h>Xd*9rP2Wm!s%2CDDbvbpw-d-dYL`i*zoS-XB+(U_t!V)=>ylV`-0
z4VyP_s;duxt9xn*=R(FI8cV=Qfas!5iTJcgBQ$xz_9A{>veCDFM|YmX=?`qc*gB)}
zm!jCxiSB#B7EKh0=*j4+=)M<ixW5x!9liQM1JG9BKL{jN(23?)eNoJ)8oBYNTW;O|
z2j7l2Ncy7=?SI1_e@;<address@hidden|d`yAdMynq9pe~LdF
ze+l>gl;=>do<G!+W6o`6Zgn(1kSiKxDf+^i)wiw6aeWiIhOMTP;O3pxoi{~Pb`|m`
zSJQ4F&dveD#u(V9<b6Vb`P&O$utl_esrU)n5qlBo?<38-ihP!ZO21($eV9v`99|Zu
z23rm$PdL6^SZ~i9MB6L16(Zg_#xAt^BG=|address@hidden
ztm2;=L)P3oysU06MOK#XI45lNQ%4<Xm>z%WrU*tGJV?xUR%4{cVW5Ahpj07#;FlQn
zUn-HgtwfPEH#y2$imWV+th_1Ssh!A#oLlXOQu|YmeXr0l#qlTUusROG%i(ZYYa^>@
zlaLDaoOztyiGUCu_nll7*{?aS!wF&ZM0*(T>)SAHT>UyiLBY6_tJ(|umYgX6dH+FM
zz1?H)KZqk~o~k~g07ly<_3itO<Alf2ryt&yN4-7tP9q(^r^Cvwf|GQN+3v;BWgEtx
zTL`)9sz9V2=fH^oC|b^nd#ZE-2h}&JpYXVeT6;m?z87)2`R`F>^(v^^4L5X%ZSggk
z)Y7&!nYOZpYn%;1>{w%Kn2rUJ#-*mB1h1{|cP$veQ2_4jtfrc|B$L>2E}L!m5q5d$
z1fM+0)$tS#c+ormI9-=Wwri);address@hidden&address@hidden)!O?NDQXeC}n#CN`H
zKg;5g>u78V<7?SZKiJ#+xJ*udsP``)k4~f6AKm|^FFNY*yy%%}(RgQce~Q0=9p^pw
zYB-v(<address@hidden>{0%oGE)wxQr_b*^n5I5Idg?r;79J66spGUIz9-Fy1LqUMu8unF
zeKd0($0IY^Ex;&h-IF;Vx~0M2x+i-+w4}k;x<_O}*Wy{p9$O|fw?3fC%eeg7hDlt$
zvcb#c*EAH;zW$zp^X<2^fKdCjEg;jrvIRuiuW11ZG#lSz#|_-NG9671#vgTNAeB9C
address@hidden>e%)<3>l>;(I(9`WnXs8HM|)Gi)&KJdS4pdwiKTGzuYp8rm7(
zGfp-zG1Kuh8Yq#u$(fE<address@hidden&k)J(@o<VumVM|2UW=TDzG20^6!^cB5BO0J-iHVCzK
z*_7a0bB?TxP^N8Ji6y!BY3;m5-<9Ir`}B$PT8L6KJnx>@address@hidden@*n
zi7njIcYg0bo;tsEUK<b>qDxz65^i=r`tQJq^0V{^7;v>=psQ%K+W^KhYJ8>y;gYTr
zKlE2dD(c;RV>X}2Xd(h*6yGy=KKm2=NewyuM}U?2g&xsYX=k8epFD;KH9HOt(r`=@
zRf|MbgR|Y1vImoRR<dV+!CBzC_C7k8S(*LG0FEQLw3ajx+k;y8qh~u0;NUJFAKv?D
z8fbVp{*AZj8<>{h;2$b3UCM`_jl$<qScE}E-Fg=($i!^o^yG;address@hidden
z&XKQ>c+0c#M=!}jK{I>?uw+iMgVf9oa8b77w!eu#>address@hidden)JRLV
z_^m~^c0IMvM=LOU(address@hidden;T&DmZ>LTaI}e}>><i$n~9i%HlS
zg0a+)z|rn47t;yGh_?MK9c;t5PRLgeBHE!RaN3WU#!+uNA*&7<address@hidden|yXC
z3#z;XmD|<~LY+d+hEa(address@hidden;S=Rn>fOFZcC0bNZPSom<r0N%P+h;tsBK`_c
address@hidden@_V=f`_Mu9#rcO=AR&_WHMF4dV>Qqu0;-kCvVI;B&c-k
zVM1l2$;address@hidden<oCmz>!Ttd38J^<F*&hcHIs4bW
zNlyal%rCe^6IzhyqjAg%`s!NN1o^e;@_}P&address@hidden|address@hidden
zbm$lj27qdg5{*x*DFTiZ^20#J(?*&JmUgEa9RHRuz$Kfkf1^zA9|bs){dr23a>Lb>
address@hidden(address@hidden>xx9WSqR=&V9jz{Pr6L<?AfSx>)B*WXa?-%D`Dczv<Mb
zl$Fm!?&~>nXDO*OY8BQqhCR{Ve1qpqTB-ydK=*zJZ)dr*s#j<address@hidden@|address@hidden
zE7|$z5&wUIjJ6sLxOyJ|I-i{nP<uK8CaFui>lIR~91)=5<WiCL4Awzs>a(hz)-$x;
z+20LcuZ&D~s#NMSe=(Nu?vnr1f&P(0{r6LE<#hUIAj>)p*S(>fzWQNe9iH#nI^!>C
zzj|ML?ft7?!uP$y$=6<dKYoA`<m|_vi=DI8m&eZ8>address@hidden|2_64G<^5o`<xTgIhJyV)
address@hidden&BJi*n*R8HF4RzX=1n+$i|`HiM35qf(L}FAwfvm+?f23A{`a}v
ze||r{Uwa0P^SlB!+*FCEO?^L>bs_4=x*Mj935W*AwBKj7v!{RR(wy&43y6CAPu)7l
address@hidden;BpA{kg|4RP_5?K0w0SuIR
AD*ylh

literal 0
HcmV?d00001

diff --git a/roms/Makefile b/roms/Makefile
index 2721b02..b88a3fd 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -1,5 +1,5 @@
 
-vgabios_variants := stdvga cirrus vmware qxl isavga
+vgabios_variants := stdvga cirrus vmware qxl isavga virtio
 vgabios_targets  := $(subst -isavga,,$(patsubst 
%,vgabios-%.bin,$(vgabios_variants)))
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
 pxerom_targets   := 8086100e 80861209 10500940 10222000 10ec8139 1af41000
diff --git a/roms/config.vga.virtio b/roms/config.vga.virtio
new file mode 100644
index 0000000..9a78983
--- /dev/null
+++ b/roms/config.vga.virtio
@@ -0,0 +1,6 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=y
+CONFIG_OVERRIDE_PCI_ID=y
+CONFIG_VGA_VID=0x1af4
+CONFIG_VGA_DID=0x1010
diff --git a/vl.c b/vl.c
index bca5c95..e3ede89 100644
--- a/vl.c
+++ b/vl.c
@@ -243,6 +243,7 @@ static struct {
     { .driver = "isa-cirrus-vga",       .flag = &default_vga       },
     { .driver = "vmware-svga",          .flag = &default_vga       },
     { .driver = "qxl-vga",              .flag = &default_vga       },
+    { .driver = "virtio-vga",           .flag = &default_vga       },
 };
 
 static QemuOptsList qemu_rtc_opts = {
@@ -2085,6 +2086,11 @@ static bool cg3_vga_available(void)
     return object_class_by_name("cgthree");
 }
 
+static bool virtio_vga_available(void)
+{
+    return object_class_by_name("virtio-vga");
+}
+
 static void select_vgahw (const char *p)
 {
     const char *opts;
@@ -2111,6 +2117,13 @@ static void select_vgahw (const char *p)
             fprintf(stderr, "Error: VMWare SVGA not available\n");
             exit(0);
         }
+    } else if (strstart(p, "virtio", &opts)) {
+        if (virtio_vga_available()) {
+            vga_interface_type = VGA_VIRTIO;
+        } else {
+            fprintf(stderr, "Error: Virtio VGA not available\n");
+            exit(0);
+        }
     } else if (strstart(p, "xenfb", &opts)) {
         vga_interface_type = VGA_XENFB;
     } else if (strstart(p, "qxl", &opts)) {
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]