|
Justin M. Forbes |
a81953 |
From ee782dec6adaced9c5bb99d02253505fb635fa12 Mon Sep 17 00:00:00 2001
|
|
Justin M. Forbes |
a81953 |
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
Justin M. Forbes |
a81953 |
Date: Fri, 12 Mar 2010 16:26:18 +0100
|
|
Justin M. Forbes |
a81953 |
Subject: [PATCH 17/39] spice: add pci vdi port backend (obsolete).
|
|
Justin M. Forbes |
a81953 |
|
|
Justin M. Forbes |
a81953 |
This is *not* intended to be merged upstream. It is just here
|
|
Justin M. Forbes |
a81953 |
because the virtio-serial windows guest drivers are not ready,
|
|
Justin M. Forbes |
a81953 |
so you can't go with the new spice-vmc yet.
|
|
Justin M. Forbes |
a81953 |
---
|
|
Justin M. Forbes |
a81953 |
Makefile.target | 2 +-
|
|
Justin M. Forbes |
a81953 |
hw/spice-vdi.c | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Justin M. Forbes |
a81953 |
2 files changed, 557 insertions(+), 1 deletions(-)
|
|
Justin M. Forbes |
a81953 |
create mode 100644 hw/spice-vdi.c
|
|
Justin M. Forbes |
a81953 |
|
|
Justin M. Forbes |
a81953 |
diff --git a/Makefile.target b/Makefile.target
|
|
Justin M. Forbes |
a81953 |
index 90544c5..025bdb8 100644
|
|
Justin M. Forbes |
a81953 |
--- a/Makefile.target
|
|
Justin M. Forbes |
a81953 |
+++ b/Makefile.target
|
|
Justin M. Forbes |
a81953 |
@@ -217,7 +217,7 @@ obj-i386-y += pc_piix.o
|
|
Justin M. Forbes |
a81953 |
obj-i386-y += testdev.o
|
|
Justin M. Forbes |
a81953 |
obj-i386-y += acpi.o acpi_piix4.o
|
|
Justin M. Forbes |
a81953 |
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
|
Justin M. Forbes |
a81953 |
-obj-i386-$(CONFIG_SPICE) += spice-vmc.o
|
|
Justin M. Forbes |
a81953 |
+obj-i386-$(CONFIG_SPICE) += spice-vmc.o spice-vdi.o
|
|
Justin M. Forbes |
a81953 |
|
|
Justin M. Forbes |
a81953 |
obj-i386-y += pcspk.o i8254.o
|
|
Justin M. Forbes |
a81953 |
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
|
Justin M. Forbes |
a81953 |
diff --git a/hw/spice-vdi.c b/hw/spice-vdi.c
|
|
Justin M. Forbes |
a81953 |
new file mode 100644
|
|
Justin M. Forbes |
a81953 |
index 0000000..23cbbe1
|
|
Justin M. Forbes |
a81953 |
--- /dev/null
|
|
Justin M. Forbes |
a81953 |
+++ b/hw/spice-vdi.c
|
|
Justin M. Forbes |
a81953 |
@@ -0,0 +1,556 @@
|
|
Justin M. Forbes |
a81953 |
+#include <pthread.h>
|
|
Justin M. Forbes |
a81953 |
+#include <signal.h>
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#include "qemu-common.h"
|
|
Justin M. Forbes |
a81953 |
+#include "qemu-spice.h"
|
|
Justin M. Forbes |
a81953 |
+#include "hw/hw.h"
|
|
Justin M. Forbes |
a81953 |
+#include "hw/pc.h"
|
|
Justin M. Forbes |
a81953 |
+#include "hw/pci.h"
|
|
Justin M. Forbes |
a81953 |
+#include "console.h"
|
|
Justin M. Forbes |
a81953 |
+#include "hw/vga_int.h"
|
|
Justin M. Forbes |
a81953 |
+#include "qemu-timer.h"
|
|
Justin M. Forbes |
a81953 |
+#include "sysemu.h"
|
|
Justin M. Forbes |
a81953 |
+#include "console.h"
|
|
Justin M. Forbes |
a81953 |
+#include "pci.h"
|
|
Justin M. Forbes |
a81953 |
+#include "hw.h"
|
|
Justin M. Forbes |
a81953 |
+#include "cpu-common.h"
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#include <spice.h>
|
|
Justin M. Forbes |
a81953 |
+#include <spice-experimental.h>
|
|
Justin M. Forbes |
a81953 |
+#include <spice/ipc_ring.h>
|
|
Justin M. Forbes |
a81953 |
+#include <spice/barrier.h>
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#undef SPICE_RING_PROD_ITEM
|
|
Justin M. Forbes |
a81953 |
+#define SPICE_RING_PROD_ITEM(r, ret) { \
|
|
Justin M. Forbes |
a81953 |
+ typeof(r) start = r; \
|
|
Justin M. Forbes |
a81953 |
+ typeof(r) end = r + 1; \
|
|
Justin M. Forbes |
a81953 |
+ uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
|
Justin M. Forbes |
a81953 |
+ typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
|
Justin M. Forbes |
a81953 |
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
|
Justin M. Forbes |
a81953 |
+ abort(); \
|
|
Justin M. Forbes |
a81953 |
+ } \
|
|
Justin M. Forbes |
a81953 |
+ ret = &m_item->el; \
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#undef SPICE_RING_CONS_ITEM
|
|
Justin M. Forbes |
a81953 |
+#define SPICE_RING_CONS_ITEM(r, ret) { \
|
|
Justin M. Forbes |
a81953 |
+ typeof(r) start = r; \
|
|
Justin M. Forbes |
a81953 |
+ typeof(r) end = r + 1; \
|
|
Justin M. Forbes |
a81953 |
+ uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
|
Justin M. Forbes |
a81953 |
+ typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
|
Justin M. Forbes |
a81953 |
+ if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
|
Justin M. Forbes |
a81953 |
+ abort(); \
|
|
Justin M. Forbes |
a81953 |
+ } \
|
|
Justin M. Forbes |
a81953 |
+ ret = &m_item->el; \
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#undef ALIGN
|
|
Justin M. Forbes |
a81953 |
+#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#define REDHAT_PCI_VENDOR_ID 0x1b36
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_DEVICE_ID 0x0105
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_REVISION 0x01
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_INTERRUPT (1 << 0)
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_MAGIC (*(uint32_t*)"VDIP")
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_DEV_NAME "vdi_port"
|
|
Justin M. Forbes |
a81953 |
+#define VDI_PORT_SAVE_VERSION 20
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#include <spice/start-packed.h>
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+typedef struct SPICE_ATTR_PACKED VDIPortPacket {
|
|
Justin M. Forbes |
a81953 |
+ uint32_t gen;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t size;
|
|
Justin M. Forbes |
a81953 |
+ uint8_t data[512 - 2 * sizeof(uint32_t)];
|
|
Justin M. Forbes |
a81953 |
+} VDIPortPacket;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+SPICE_RING_DECLARE(VDIPortRing, VDIPortPacket, 32);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+enum {
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_IO_RANGE_INDEX,
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_RAM_RANGE_INDEX,
|
|
Justin M. Forbes |
a81953 |
+};
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+enum {
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_IO_CONNECTION,
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_IO_NOTIFY = 4,
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_IO_UPDATE_IRQ = 8,
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ VDI_PORT_IO_RANGE_SIZE = 12
|
|
Justin M. Forbes |
a81953 |
+};
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+typedef struct SPICE_ATTR_PACKED VDIPortRam {
|
|
Justin M. Forbes |
a81953 |
+ uint32_t magic;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t generation;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t int_pending;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t int_mask;
|
|
Justin M. Forbes |
a81953 |
+ VDIPortRing input;
|
|
Justin M. Forbes |
a81953 |
+ VDIPortRing output;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t reserv[32];
|
|
Justin M. Forbes |
a81953 |
+} VDIPortRam;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+#include <spice/end-packed.h>
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+typedef struct PCIVDIPortDevice {
|
|
Justin M. Forbes |
a81953 |
+ PCIDevice pci_dev;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t io_base;
|
|
Justin M. Forbes |
a81953 |
+ uint64_t ram_offset;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t ram_size;
|
|
Justin M. Forbes |
a81953 |
+ VDIPortRam *ram;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t connected;
|
|
Justin M. Forbes |
a81953 |
+ int running;
|
|
Justin M. Forbes |
a81953 |
+ int new_gen_on_resume;
|
|
Justin M. Forbes |
a81953 |
+ int active_interface;
|
|
Justin M. Forbes |
a81953 |
+ SpiceVDIPortInstance sin;
|
|
Justin M. Forbes |
a81953 |
+ int plug_read_pos;
|
|
Justin M. Forbes |
a81953 |
+} PCIVDIPortDevice;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int debug = 1;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static inline uint32_t msb_mask(uint32_t val)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ uint32_t mask;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ do {
|
|
Justin M. Forbes |
a81953 |
+ mask = ~(val - 1) & val;
|
|
Justin M. Forbes |
a81953 |
+ val &= ~mask;
|
|
Justin M. Forbes |
a81953 |
+ } while (mask < val);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ return mask;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static inline void atomic_or(uint32_t *var, uint32_t add)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ __asm__ __volatile__ ("lock; orl %1, %0" : "+m" (*var) : "r" (add) : "memory");
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static inline uint32_t atomic_exchange(uint32_t val, uint32_t *ptr)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ __asm__ __volatile__("xchgl %0, %1" : "+q"(val), "+m" (*ptr) : : "memory");
|
|
Justin M. Forbes |
a81953 |
+ return val;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void set_dirty(void *base, ram_addr_t offset, void *start, uint32_t length)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ assert(start >= base);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ ram_addr_t addr = (ram_addr_t)((uint8_t*)start - (uint8_t*)base) + offset;
|
|
Justin M. Forbes |
a81953 |
+ ram_addr_t end = ALIGN(addr + length, TARGET_PAGE_SIZE);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ do {
|
|
Justin M. Forbes |
a81953 |
+ cpu_physical_memory_set_dirty(addr);
|
|
Justin M. Forbes |
a81953 |
+ addr += TARGET_PAGE_SIZE;
|
|
Justin M. Forbes |
a81953 |
+ } while ( addr < end );
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static inline void vdi_port_set_dirty(PCIVDIPortDevice *d, void *start, uint32_t length)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ set_dirty(d->ram, d->ram_offset, start, length);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_new_gen(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ d->ram->generation = (d->ram->generation + 1 == 0) ? 1 : d->ram->generation + 1;
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, &d->ram->generation, sizeof(d->ram->generation));
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_irq_level(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ return !!(d->ram->int_pending & d->ram->int_mask);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_notify_guest(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ uint32_t events = VDI_PORT_INTERRUPT;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t old_pending;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (!d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ old_pending = __sync_fetch_and_or(&d->ram->int_pending, events);
|
|
Justin M. Forbes |
a81953 |
+ if ((old_pending & events) == events) {
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, &d->ram->int_pending, sizeof(d->ram->int_pending));
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_interface_write(SpiceVDIPortInstance *sin,
|
|
Justin M. Forbes |
a81953 |
+ const uint8_t *buf, int len)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
|
Justin M. Forbes |
a81953 |
+ VDIPortRing *ring = &d->ram->output;
|
|
Justin M. Forbes |
a81953 |
+ int do_notify = false;
|
|
Justin M. Forbes |
a81953 |
+ int actual_write = 0;
|
|
Justin M. Forbes |
a81953 |
+ int l = len;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (!d->running) {
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ while (len) {
|
|
Justin M. Forbes |
a81953 |
+ VDIPortPacket *packet;
|
|
Justin M. Forbes |
a81953 |
+ int notify;
|
|
Justin M. Forbes |
a81953 |
+ int wait;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_PROD_WAIT(ring, wait);
|
|
Justin M. Forbes |
a81953 |
+ if (wait) {
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_PROD_ITEM(ring, packet);
|
|
Justin M. Forbes |
a81953 |
+ packet->gen = d->ram->generation;
|
|
Justin M. Forbes |
a81953 |
+ packet->size = MIN(len, sizeof(packet->data));
|
|
Justin M. Forbes |
a81953 |
+ memcpy(packet->data, buf, packet->size);
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, packet, sizeof(*packet) - (sizeof(packet->data) - packet->size));
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_PUSH(ring, notify);
|
|
Justin M. Forbes |
a81953 |
+ do_notify = do_notify || notify;
|
|
Justin M. Forbes |
a81953 |
+ len -= packet->size;
|
|
Justin M. Forbes |
a81953 |
+ buf += packet->size;
|
|
Justin M. Forbes |
a81953 |
+ actual_write += packet->size;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (do_notify) {
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_notify_guest(d);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ if (debug > 1) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_write, l);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return actual_write;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_interface_read(SpiceVDIPortInstance *sin,
|
|
Justin M. Forbes |
a81953 |
+ uint8_t *buf, int len)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = container_of(sin, PCIVDIPortDevice, sin);
|
|
Justin M. Forbes |
a81953 |
+ VDIPortRing *ring = &d->ram->input;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t gen = d->ram->generation;
|
|
Justin M. Forbes |
a81953 |
+ VDIPortPacket *packet;
|
|
Justin M. Forbes |
a81953 |
+ int do_notify = false;
|
|
Justin M. Forbes |
a81953 |
+ int actual_read = 0;
|
|
Justin M. Forbes |
a81953 |
+ int l = len;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (!d->running) {
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ while (!SPICE_RING_IS_EMPTY(ring)) {
|
|
Justin M. Forbes |
a81953 |
+ int notify;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_CONS_ITEM(ring, packet);
|
|
Justin M. Forbes |
a81953 |
+ if (packet->gen == gen) {
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_POP(ring, notify);
|
|
Justin M. Forbes |
a81953 |
+ do_notify = do_notify || notify;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ while (len) {
|
|
Justin M. Forbes |
a81953 |
+ VDIPortPacket *packet;
|
|
Justin M. Forbes |
a81953 |
+ int wait;
|
|
Justin M. Forbes |
a81953 |
+ int now;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_CONS_WAIT(ring, wait);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (wait) {
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_CONS_ITEM(ring, packet);
|
|
Justin M. Forbes |
a81953 |
+ if (packet->size > sizeof(packet->data)) {
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
|
Justin M. Forbes |
a81953 |
+ printf("%s: bad packet size\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ now = MIN(len, packet->size - d->plug_read_pos);
|
|
Justin M. Forbes |
a81953 |
+ memcpy(buf, packet->data + d->plug_read_pos, now);
|
|
Justin M. Forbes |
a81953 |
+ len -= now;
|
|
Justin M. Forbes |
a81953 |
+ buf += now;
|
|
Justin M. Forbes |
a81953 |
+ actual_read += now;
|
|
Justin M. Forbes |
a81953 |
+ if ((d->plug_read_pos += now) == packet->size) {
|
|
Justin M. Forbes |
a81953 |
+ int notify;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ d->plug_read_pos = 0;
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_POP(ring, notify);
|
|
Justin M. Forbes |
a81953 |
+ do_notify = do_notify || notify;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, ring, sizeof(*ring) - sizeof(ring->items));
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (do_notify) {
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_notify_guest(d);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ if (debug > 1) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: %d/%d\n", __FUNCTION__, actual_read, l);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return actual_read;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static SpiceVDIPortInterface vdi_port_interface = {
|
|
Justin M. Forbes |
a81953 |
+ .base.type = SPICE_INTERFACE_VDI_PORT,
|
|
Justin M. Forbes |
a81953 |
+ .base.description = "vdi port",
|
|
Justin M. Forbes |
a81953 |
+ .base.major_version = SPICE_INTERFACE_VDI_PORT_MAJOR,
|
|
Justin M. Forbes |
a81953 |
+ .base.minor_version = SPICE_INTERFACE_VDI_PORT_MINOR,
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ .write = vdi_port_interface_write,
|
|
Justin M. Forbes |
a81953 |
+ .read = vdi_port_interface_read,
|
|
Justin M. Forbes |
a81953 |
+};
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_register_interface(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ if (d->active_interface ) {
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ d->sin.base.sif = &vdi_port_interface.base;
|
|
Justin M. Forbes |
a81953 |
+ spice_server_add_interface(spice_server, &d->sin.base);
|
|
Justin M. Forbes |
a81953 |
+ d->active_interface = true;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_unregister_interface(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ if (!d->active_interface ) {
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ spice_server_remove_interface(&d->sin.base);
|
|
Justin M. Forbes |
a81953 |
+ d->active_interface = false;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static uint32_t vdi_port_dev_connect(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ if (d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: already connected\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_new_gen(d);
|
|
Justin M. Forbes |
a81953 |
+ d->connected = true;
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_register_interface(d);
|
|
Justin M. Forbes |
a81953 |
+ return d->ram->generation;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_dev_disconnect(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ if (!d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ d->connected = false;
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_unregister_interface(d);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_dev_notify(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ spice_server_vdi_port_wakeup(&d->sin);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_write_dword(void *opaque, uint32_t addr, uint32_t val)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = opaque;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t io_port = addr - d->io_base;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (debug > 1) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: addr 0x%x val 0x%x\n", __FUNCTION__, addr, val);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ switch (io_port) {
|
|
Justin M. Forbes |
a81953 |
+ case VDI_PORT_IO_NOTIFY:
|
|
Justin M. Forbes |
a81953 |
+ if (!d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: not connected\n", __FUNCTION__);
|
|
Justin M. Forbes |
a81953 |
+ return;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_dev_notify(d);
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ case VDI_PORT_IO_UPDATE_IRQ:
|
|
Justin M. Forbes |
a81953 |
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ case VDI_PORT_IO_CONNECTION:
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_dev_disconnect(d);
|
|
Justin M. Forbes |
a81953 |
+ break;
|
|
Justin M. Forbes |
a81953 |
+ default:
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: unexpected addr 0x%x val 0x%x\n",
|
|
Justin M. Forbes |
a81953 |
+ __FUNCTION__, addr, val);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ };
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static uint32_t vdi_port_read_dword(void *opaque, uint32_t addr)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = opaque;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t io_port = addr - d->io_base;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (debug > 1) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: addr 0x%x\n", __FUNCTION__, addr);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ if (io_port == VDI_PORT_IO_CONNECTION) {
|
|
Justin M. Forbes |
a81953 |
+ return vdi_port_dev_connect(d);
|
|
Justin M. Forbes |
a81953 |
+ } else {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: unexpected addr 0x%x\n", __FUNCTION__, addr);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return 0xffffffff;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_io_map(PCIDevice *pci_dev, int region_num,
|
|
Justin M. Forbes |
a81953 |
+ pcibus_t addr, pcibus_t size, int type)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: base 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ d->io_base = addr;
|
|
Justin M. Forbes |
a81953 |
+ register_ioport_write(addr, size, 4, vdi_port_write_dword, pci_dev);
|
|
Justin M. Forbes |
a81953 |
+ register_ioport_read(addr, size, 4, vdi_port_read_dword, pci_dev);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_ram_map(PCIDevice *pci_dev, int region_num,
|
|
Justin M. Forbes |
a81953 |
+ pcibus_t addr, pcibus_t size, int type)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev, pci_dev);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (debug) {
|
|
Justin M. Forbes |
a81953 |
+ fprintf(stderr, "%s: addr 0x%lx size 0x%lx\n", __FUNCTION__, addr, size);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ assert((addr & (size - 1)) == 0);
|
|
Justin M. Forbes |
a81953 |
+ assert(size == d->ram_size);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ cpu_register_physical_memory(addr, size, d->ram_offset | IO_MEM_RAM);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_reset(PCIVDIPortDevice *d)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ memset(d->ram, 0, sizeof(*d->ram));
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_INIT(&d->ram->input);
|
|
Justin M. Forbes |
a81953 |
+ SPICE_RING_INIT(&d->ram->output);
|
|
Justin M. Forbes |
a81953 |
+ d->ram->magic = VDI_PORT_MAGIC;
|
|
Justin M. Forbes |
a81953 |
+ d->ram->generation = 0;
|
|
Justin M. Forbes |
a81953 |
+ d->ram->int_pending = 0;
|
|
Justin M. Forbes |
a81953 |
+ d->ram->int_mask = 0;
|
|
Justin M. Forbes |
a81953 |
+ d->connected = false;
|
|
Justin M. Forbes |
a81953 |
+ d->plug_read_pos = 0;
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_set_dirty(d, d->ram, sizeof(*d->ram));
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_reset_handler(DeviceState *dev)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *d = DO_UPCAST(PCIVDIPortDevice, pci_dev.qdev, dev);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_dev_disconnect(d);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_reset(d);
|
|
Justin M. Forbes |
a81953 |
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_pre_load(void* opaque)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice* d = opaque;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_unregister_interface(d);
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_post_load(void* opaque,int version_id)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice* d = opaque;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (d->connected) {
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_register_interface(d);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_vm_change_state_handler(void *opaque, int running, int reason)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice* d = opaque;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ if (running) {
|
|
Justin M. Forbes |
a81953 |
+ d->running = true;
|
|
Justin M. Forbes |
a81953 |
+ if (d->new_gen_on_resume) {
|
|
Justin M. Forbes |
a81953 |
+ d->new_gen_on_resume = false;
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_new_gen(d);
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_notify_guest(d);
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+ qemu_set_irq(d->pci_dev.irq[0], vdi_port_irq_level(d));
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_dev_notify(d);
|
|
Justin M. Forbes |
a81953 |
+ } else {
|
|
Justin M. Forbes |
a81953 |
+ d->running = false;
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static int vdi_port_init(PCIDevice *dev)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ PCIVDIPortDevice *vdi = (PCIVDIPortDevice *)dev;
|
|
Justin M. Forbes |
a81953 |
+ uint8_t* config = vdi->pci_dev.config;
|
|
Justin M. Forbes |
a81953 |
+ uint32_t ram_size = msb_mask(sizeof(VDIPortRam) * 2 - 1);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ vdi->ram_offset = qemu_ram_alloc(&vdi->pci_dev.qdev, "bar1", ram_size);
|
|
Justin M. Forbes |
a81953 |
+ vdi->ram = qemu_get_ram_ptr(vdi->ram_offset);
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_reset(vdi);
|
|
Justin M. Forbes |
a81953 |
+ vdi->ram_size = ram_size;
|
|
Justin M. Forbes |
a81953 |
+ vdi->new_gen_on_resume = false;
|
|
Justin M. Forbes |
a81953 |
+ vdi->running = false;
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ pci_config_set_vendor_id(config, REDHAT_PCI_VENDOR_ID);
|
|
Justin M. Forbes |
a81953 |
+ pci_config_set_device_id(config, VDI_PORT_DEVICE_ID);
|
|
Justin M. Forbes |
a81953 |
+ pci_config_set_class(config, PCI_CLASS_COMMUNICATION_OTHER);
|
|
Justin M. Forbes |
a81953 |
+ pci_set_byte(&config[PCI_REVISION_ID], VDI_PORT_REVISION);
|
|
Justin M. Forbes |
a81953 |
+ pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ pci_register_bar(dev, VDI_PORT_IO_RANGE_INDEX,
|
|
Justin M. Forbes |
a81953 |
+ msb_mask(VDI_PORT_IO_RANGE_SIZE * 2 - 1),
|
|
Justin M. Forbes |
a81953 |
+ PCI_BASE_ADDRESS_SPACE_IO, vdi_port_io_map);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ pci_register_bar(dev, VDI_PORT_RAM_RANGE_INDEX,
|
|
Justin M. Forbes |
a81953 |
+ vdi->ram_size , PCI_BASE_ADDRESS_SPACE_MEMORY,
|
|
Justin M. Forbes |
a81953 |
+ vdi_port_ram_map);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ qemu_add_vm_change_state_handler(vdi_port_vm_change_state_handler, vdi);
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ return 0;
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static VMStateDescription vdi_port_vmstate = {
|
|
Justin M. Forbes |
a81953 |
+ .name = VDI_PORT_DEV_NAME,
|
|
Justin M. Forbes |
a81953 |
+ .version_id = VDI_PORT_SAVE_VERSION,
|
|
Justin M. Forbes |
a81953 |
+ .minimum_version_id = VDI_PORT_SAVE_VERSION,
|
|
Justin M. Forbes |
a81953 |
+ .pre_load = vdi_port_pre_load,
|
|
Justin M. Forbes |
a81953 |
+ .post_load = vdi_port_post_load,
|
|
Justin M. Forbes |
a81953 |
+ .fields = (VMStateField []) {
|
|
Justin M. Forbes |
a81953 |
+ VMSTATE_PCI_DEVICE(pci_dev, PCIVDIPortDevice),
|
|
Justin M. Forbes |
a81953 |
+ VMSTATE_UINT32(connected, PCIVDIPortDevice),
|
|
Justin M. Forbes |
a81953 |
+ VMSTATE_END_OF_LIST()
|
|
Justin M. Forbes |
a81953 |
+ }
|
|
Justin M. Forbes |
a81953 |
+};
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static PCIDeviceInfo vdi_port_info = {
|
|
Justin M. Forbes |
a81953 |
+ .qdev.name = VDI_PORT_DEV_NAME,
|
|
Justin M. Forbes |
a81953 |
+ .qdev.desc = "spice virtual desktop port (obsolete)",
|
|
Justin M. Forbes |
a81953 |
+ .qdev.size = sizeof(PCIVDIPortDevice),
|
|
Justin M. Forbes |
a81953 |
+ .qdev.vmsd = &vdi_port_vmstate,
|
|
Justin M. Forbes |
a81953 |
+ .qdev.reset = vdi_port_reset_handler,
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+ .init = vdi_port_init,
|
|
Justin M. Forbes |
a81953 |
+};
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+static void vdi_port_register(void)
|
|
Justin M. Forbes |
a81953 |
+{
|
|
Justin M. Forbes |
a81953 |
+ pci_qdev_register(&vdi_port_info);
|
|
Justin M. Forbes |
a81953 |
+}
|
|
Justin M. Forbes |
a81953 |
+
|
|
Justin M. Forbes |
a81953 |
+device_init(vdi_port_register);
|
|
Justin M. Forbes |
a81953 |
--
|
|
Justin M. Forbes |
a81953 |
1.7.2.3
|
|
Justin M. Forbes |
a81953 |
|