Commit 53c25cea7d59525ca9aa3fb01cc6947bafbbfb61

Authored by Paul Brook
1 parent d8ee7665

Separate virtio PCI code

Split the PCI host bindings from the VRing transport implementation.

Signed-off-by: Paul Brook <paul@codesourcery.com>
Makefile.target
... ... @@ -489,7 +489,8 @@ OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \
489 489 gdbstub.o gdbstub-xml.o sysbus.o
490 490 # virtio has to be here due to weird dependency between PCI and virtio-net.
491 491 # need to fix this properly
492   -OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
  492 +OBJS+=virtio.o virtio-pci.o
  493 +OBJS+=virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
493 494 OBJS+=fw_cfg.o
494 495 ifdef CONFIG_KVM
495 496 OBJS+=kvm.o kvm-all.o
... ...
... ... @@ -1137,21 +1137,21 @@ static void pc_init1(ram_addr_t ram_size,
1137 1137 int unit_id = 0;
1138 1138  
1139 1139 while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
1140   - pci_create_simple(pci_bus, -1, "virtio-blk");
  1140 + pci_create_simple(pci_bus, -1, "virtio-blk-pci");
1141 1141 unit_id++;
1142 1142 }
1143 1143 }
1144 1144  
1145 1145 /* Add virtio balloon device */
1146 1146 if (pci_enabled) {
1147   - pci_create_simple(pci_bus, -1, "virtio-balloon");
  1147 + pci_create_simple(pci_bus, -1, "virtio-balloon-pci");
1148 1148 }
1149 1149  
1150 1150 /* Add virtio console devices */
1151 1151 if (pci_enabled) {
1152 1152 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
1153 1153 if (virtcon_hds[i]) {
1154   - pci_create_simple(pci_bus, -1, "virtio-console");
  1154 + pci_create_simple(pci_bus, -1, "virtio-console-pci");
1155 1155 }
1156 1156 }
1157 1157 }
... ...
hw/pci-hotplug.c
... ... @@ -120,7 +120,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, PCIBus *pci_bus,
120 120 opaque = pci_create_simple(pci_bus, -1, "lsi53c895a");
121 121 break;
122 122 case IF_VIRTIO:
123   - opaque = pci_create_simple(pci_bus, -1, "virtio-blk");
  123 + opaque = pci_create_simple(pci_bus, -1, "virtio-blk-pci");
124 124 qdev_init(opaque);
125 125 break;
126 126 }
... ...
hw/pci.c
... ... @@ -806,7 +806,7 @@ static const char * const pci_nic_names[] = {
806 806 "rtl8139",
807 807 "e1000",
808 808 "pcnet",
809   - "virtio_net",
  809 + "virtio-net-pci",
810 810 NULL
811 811 };
812 812  
... ...
hw/ppc440_bamboo.c
... ... @@ -111,14 +111,14 @@ static void bamboo_init(ram_addr_t ram_size,
111 111  
112 112 /* Add virtio block devices. */
113 113 while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
114   - pci_create_simple(pcibus, -1, "virtio-blk");
  114 + pci_create_simple(pcibus, -1, "virtio-blk-pci");
115 115 unit_id++;
116 116 }
117 117  
118 118 /* Add virtio console devices */
119 119 for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
120 120 if (virtcon_hds[i]) {
121   - pci_create_simple(pcibus, -1, "virtio-console");
  121 + pci_create_simple(pcibus, -1, "virtio-console-pci");
122 122 }
123 123 }
124 124  
... ...
hw/ppce500_mpc8544ds.c
... ... @@ -220,7 +220,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
220 220  
221 221 /* Add virtio block devices. */
222 222 while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
223   - pci_create_simple(pci_bus, -1, "virtio-blk");
  223 + pci_create_simple(pci_bus, -1, "virtio-blk-pci");
224 224 unit_id++;
225 225 }
226 226  
... ...
hw/virtio-balloon.c
... ... @@ -169,17 +169,13 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
169 169 return 0;
170 170 }
171 171  
172   -static void virtio_balloon_init(PCIDevice *pci_dev)
  172 +VirtIODevice *virtio_balloon_init(DeviceState *dev)
173 173 {
174 174 VirtIOBalloon *s;
175 175  
176   - s = (VirtIOBalloon *)virtio_init_pci(pci_dev, "virtio-balloon",
177   - PCI_VENDOR_ID_REDHAT_QUMRANET,
178   - PCI_DEVICE_ID_VIRTIO_BALLOON,
179   - PCI_VENDOR_ID_REDHAT_QUMRANET,
180   - VIRTIO_ID_BALLOON,
181   - PCI_CLASS_MEMORY_RAM, 0x00,
182   - 8);
  176 + s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
  177 + VIRTIO_ID_BALLOON,
  178 + 8, sizeof(VirtIOBalloon));
183 179  
184 180 s->vdev.get_config = virtio_balloon_get_config;
185 181 s->vdev.set_config = virtio_balloon_set_config;
... ... @@ -191,12 +187,6 @@ static void virtio_balloon_init(PCIDevice *pci_dev)
191 187 qemu_add_balloon_handler(virtio_balloon_to_target, s);
192 188  
193 189 register_savevm("virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s);
194   -}
195 190  
196   -static void virtio_balloon_register_devices(void)
197   -{
198   - pci_qdev_register("virtio-balloon", sizeof(VirtIOBalloon),
199   - virtio_balloon_init);
  191 + return &s->vdev;
200 192 }
201   -
202   -device_init(virtio_balloon_register_devices)
... ...
hw/virtio-blk.c
... ... @@ -348,28 +348,24 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
348 348 return 0;
349 349 }
350 350  
351   -static void virtio_blk_init(PCIDevice *pci_dev)
  351 +VirtIODevice *virtio_blk_init(DeviceState *dev)
352 352 {
353 353 VirtIOBlock *s;
354 354 int cylinders, heads, secs;
355 355 static int virtio_blk_id;
356 356 BlockDriverState *bs;
357 357  
358   - s = (VirtIOBlock *)virtio_init_pci(pci_dev, "virtio-blk",
359   - PCI_VENDOR_ID_REDHAT_QUMRANET,
360   - PCI_DEVICE_ID_VIRTIO_BLOCK,
361   - PCI_VENDOR_ID_REDHAT_QUMRANET,
362   - VIRTIO_ID_BLOCK,
363   - PCI_CLASS_STORAGE_OTHER, 0x00,
364   - sizeof(struct virtio_blk_config));
  358 + s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
  359 + sizeof(struct virtio_blk_config),
  360 + sizeof(VirtIOBlock));
365 361  
366   - bs = qdev_init_bdrv(&pci_dev->qdev, IF_VIRTIO);
  362 + bs = qdev_init_bdrv(dev, IF_VIRTIO);
367 363 s->vdev.get_config = virtio_blk_update_config;
368 364 s->vdev.get_features = virtio_blk_get_features;
369 365 s->vdev.reset = virtio_blk_reset;
370 366 s->bs = bs;
371 367 s->rq = NULL;
372   - bs->private = &s->vdev.pci_dev;
  368 + bs->private = dev;
373 369 bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
374 370 bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
375 371  
... ... @@ -378,11 +374,6 @@ static void virtio_blk_init(PCIDevice *pci_dev)
378 374 qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
379 375 register_savevm("virtio-blk", virtio_blk_id++, 2,
380 376 virtio_blk_save, virtio_blk_load, s);
381   -}
382 377  
383   -static void virtio_blk_register_devices(void)
384   -{
385   - pci_qdev_register("virtio-blk", sizeof(VirtIOBlock), virtio_blk_init);
  378 + return &s->vdev;
386 379 }
387   -
388   -device_init(virtio_blk_register_devices)
... ...
hw/virtio-blk.h
... ... @@ -16,7 +16,6 @@
16 16  
17 17 #include "virtio.h"
18 18 #include "block.h"
19   -#include "pci.h"
20 19  
21 20 /* from Linux's linux/virtio_blk.h */
22 21  
... ...
hw/virtio-console.c
... ... @@ -123,31 +123,21 @@ static int virtio_console_load(QEMUFile *f, void *opaque, int version_id)
123 123 return 0;
124 124 }
125 125  
126   -static void virtio_console_init(PCIDevice *pci_dev)
  126 +VirtIODevice *virtio_console_init(DeviceState *dev)
127 127 {
128 128 VirtIOConsole *s;
129   - s = (VirtIOConsole *)virtio_init_pci(pci_dev, "virtio-console",
130   - PCI_VENDOR_ID_REDHAT_QUMRANET,
131   - PCI_DEVICE_ID_VIRTIO_CONSOLE,
132   - PCI_VENDOR_ID_REDHAT_QUMRANET,
133   - VIRTIO_ID_CONSOLE,
134   - PCI_CLASS_DISPLAY_OTHER, 0x00,
135   - 0);
  129 + s = (VirtIOConsole *)virtio_common_init("virtio-console",
  130 + VIRTIO_ID_CONSOLE,
  131 + 0, sizeof(VirtIOConsole));
136 132 s->vdev.get_features = virtio_console_get_features;
137 133  
138 134 s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input);
139 135 s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output);
140 136  
141   - s->chr = qdev_init_chardev(&pci_dev->qdev);
  137 + s->chr = qdev_init_chardev(dev);
142 138 qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s);
143 139  
144 140 register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s);
145   -}
146 141  
147   -static void virtio_console_register_devices(void)
148   -{
149   - pci_qdev_register("virtio-console", sizeof(VirtIOConsole),
150   - virtio_console_init);
  142 + return &s->vdev;
151 143 }
152   -
153   -device_init(virtio_console_register_devices)
... ...
hw/virtio-net.c
... ... @@ -585,18 +585,14 @@ static void virtio_net_cleanup(VLANClientState *vc)
585 585 virtio_cleanup(&n->vdev);
586 586 }
587 587  
588   -static void virtio_net_init(PCIDevice *pci_dev)
  588 +VirtIODevice *virtio_net_init(DeviceState *dev)
589 589 {
590 590 VirtIONet *n;
591 591 static int virtio_net_id;
592 592  
593   - n = (VirtIONet *)virtio_init_pci(pci_dev, "virtio-net",
594   - PCI_VENDOR_ID_REDHAT_QUMRANET,
595   - PCI_DEVICE_ID_VIRTIO_NET,
596   - PCI_VENDOR_ID_REDHAT_QUMRANET,
597   - VIRTIO_ID_NET,
598   - PCI_CLASS_NETWORK_ETHERNET, 0x00,
599   - sizeof(struct virtio_net_config));
  593 + n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
  594 + sizeof(struct virtio_net_config),
  595 + sizeof(VirtIONet));
600 596  
601 597 n->vdev.get_config = virtio_net_get_config;
602 598 n->vdev.set_config = virtio_net_set_config;
... ... @@ -607,9 +603,9 @@ static void virtio_net_init(PCIDevice *pci_dev)
607 603 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
608 604 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
609 605 n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl);
610   - qdev_get_macaddr(&pci_dev->qdev, n->mac);
  606 + qdev_get_macaddr(dev, n->mac);
611 607 n->status = VIRTIO_NET_S_LINK_UP;
612   - n->vc = qdev_get_vlan_client(&pci_dev->qdev,
  608 + n->vc = qdev_get_vlan_client(dev,
613 609 virtio_net_receive,
614 610 virtio_net_can_receive,
615 611 virtio_net_cleanup, n);
... ... @@ -628,11 +624,6 @@ static void virtio_net_init(PCIDevice *pci_dev)
628 624  
629 625 register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
630 626 virtio_net_save, virtio_net_load, n);
631   -}
632 627  
633   -static void virtio_net_register_devices(void)
634   -{
635   - pci_qdev_register("virtio_net", sizeof(VirtIONet), virtio_net_init);
  628 + return &n->vdev;
636 629 }
637   -
638   -device_init(virtio_net_register_devices)
... ...
hw/virtio-pci.c 0 โ†’ 100644
  1 +/*
  2 + * Virtio PCI Bindings
  3 + *
  4 + * Copyright IBM, Corp. 2007
  5 + * Copyright (c) 2009 CodeSourcery
  6 + *
  7 + * Authors:
  8 + * Anthony Liguori <aliguori@us.ibm.com>
  9 + * Paul Brook <paul@codesourcery.com>
  10 + *
  11 + * This work is licensed under the terms of the GNU GPL, version 2. See
  12 + * the COPYING file in the top-level directory.
  13 + *
  14 + */
  15 +
  16 +#include <inttypes.h>
  17 +
  18 +#include "virtio.h"
  19 +#include "pci.h"
  20 +#include "sysemu.h"
  21 +
  22 +/* from Linux's linux/virtio_pci.h */
  23 +
  24 +/* A 32-bit r/o bitmask of the features supported by the host */
  25 +#define VIRTIO_PCI_HOST_FEATURES 0
  26 +
  27 +/* A 32-bit r/w bitmask of features activated by the guest */
  28 +#define VIRTIO_PCI_GUEST_FEATURES 4
  29 +
  30 +/* A 32-bit r/w PFN for the currently selected queue */
  31 +#define VIRTIO_PCI_QUEUE_PFN 8
  32 +
  33 +/* A 16-bit r/o queue size for the currently selected queue */
  34 +#define VIRTIO_PCI_QUEUE_NUM 12
  35 +
  36 +/* A 16-bit r/w queue selector */
  37 +#define VIRTIO_PCI_QUEUE_SEL 14
  38 +
  39 +/* A 16-bit r/w queue notifier */
  40 +#define VIRTIO_PCI_QUEUE_NOTIFY 16
  41 +
  42 +/* An 8-bit device status register. */
  43 +#define VIRTIO_PCI_STATUS 18
  44 +
  45 +/* An 8-bit r/o interrupt status register. Reading the value will return the
  46 + * current contents of the ISR and will also clear it. This is effectively
  47 + * a read-and-acknowledge. */
  48 +#define VIRTIO_PCI_ISR 19
  49 +
  50 +#define VIRTIO_PCI_CONFIG 20
  51 +
  52 +/* Virtio ABI version, if we increment this, we break the guest driver. */
  53 +#define VIRTIO_PCI_ABI_VERSION 0
  54 +
  55 +/* How many bits to shift physical queue address written to QUEUE_PFN.
  56 + * 12 is historical, and due to x86 page size. */
  57 +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
  58 +
  59 +/* QEMU doesn't strictly need write barriers since everything runs in
  60 + * lock-step. We'll leave the calls to wmb() in though to make it obvious for
  61 + * KVM or if kqemu gets SMP support.
  62 + */
  63 +#define wmb() do { } while (0)
  64 +
  65 +/* PCI bindings. */
  66 +
  67 +typedef struct {
  68 + PCIDevice pci_dev;
  69 + VirtIODevice *vdev;
  70 + uint32_t addr;
  71 +
  72 + uint16_t vendor;
  73 + uint16_t device;
  74 + uint16_t subvendor;
  75 + uint16_t class_code;
  76 + uint8_t pif;
  77 +} VirtIOPCIProxy;
  78 +
  79 +/* virtio device */
  80 +
  81 +static void virtio_pci_update_irq(void *opaque)
  82 +{
  83 + VirtIOPCIProxy *proxy = opaque;
  84 +
  85 + qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
  86 +}
  87 +
  88 +static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  89 +{
  90 + VirtIOPCIProxy *proxy = opaque;
  91 + VirtIODevice *vdev = proxy->vdev;
  92 + target_phys_addr_t pa;
  93 +
  94 + addr -= proxy->addr;
  95 +
  96 + switch (addr) {
  97 + case VIRTIO_PCI_GUEST_FEATURES:
  98 + /* Guest does not negotiate properly? We have to assume nothing. */
  99 + if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
  100 + if (vdev->bad_features)
  101 + val = vdev->bad_features(vdev);
  102 + else
  103 + val = 0;
  104 + }
  105 + if (vdev->set_features)
  106 + vdev->set_features(vdev, val);
  107 + vdev->features = val;
  108 + break;
  109 + case VIRTIO_PCI_QUEUE_PFN:
  110 + pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
  111 + virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
  112 + break;
  113 + case VIRTIO_PCI_QUEUE_SEL:
  114 + if (val < VIRTIO_PCI_QUEUE_MAX)
  115 + vdev->queue_sel = val;
  116 + break;
  117 + case VIRTIO_PCI_QUEUE_NOTIFY:
  118 + virtio_queue_notify(vdev, val);
  119 + break;
  120 + case VIRTIO_PCI_STATUS:
  121 + vdev->status = val & 0xFF;
  122 + if (vdev->status == 0)
  123 + virtio_reset(vdev);
  124 + break;
  125 + }
  126 +}
  127 +
  128 +static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
  129 +{
  130 + VirtIOPCIProxy *proxy = opaque;
  131 + VirtIODevice *vdev = proxy->vdev;
  132 + uint32_t ret = 0xFFFFFFFF;
  133 +
  134 + addr -= proxy->addr;
  135 +
  136 + switch (addr) {
  137 + case VIRTIO_PCI_HOST_FEATURES:
  138 + ret = vdev->get_features(vdev);
  139 + ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
  140 + break;
  141 + case VIRTIO_PCI_GUEST_FEATURES:
  142 + ret = vdev->features;
  143 + break;
  144 + case VIRTIO_PCI_QUEUE_PFN:
  145 + ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
  146 + >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
  147 + break;
  148 + case VIRTIO_PCI_QUEUE_NUM:
  149 + ret = virtio_queue_get_num(vdev, vdev->queue_sel);
  150 + break;
  151 + case VIRTIO_PCI_QUEUE_SEL:
  152 + ret = vdev->queue_sel;
  153 + break;
  154 + case VIRTIO_PCI_STATUS:
  155 + ret = vdev->status;
  156 + break;
  157 + case VIRTIO_PCI_ISR:
  158 + /* reading from the ISR also clears it. */
  159 + ret = vdev->isr;
  160 + vdev->isr = 0;
  161 + virtio_update_irq(vdev);
  162 + break;
  163 + default:
  164 + break;
  165 + }
  166 +
  167 + return ret;
  168 +}
  169 +
  170 +static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
  171 +{
  172 + VirtIOPCIProxy *proxy = opaque;
  173 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  174 + return virtio_config_readb(proxy->vdev, addr);
  175 +}
  176 +
  177 +static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
  178 +{
  179 + VirtIOPCIProxy *proxy = opaque;
  180 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  181 + return virtio_config_readw(proxy->vdev, addr);
  182 +}
  183 +
  184 +static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
  185 +{
  186 + VirtIOPCIProxy *proxy = opaque;
  187 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  188 + return virtio_config_readl(proxy->vdev, addr);
  189 +}
  190 +
  191 +static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
  192 +{
  193 + VirtIOPCIProxy *proxy = opaque;
  194 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  195 + virtio_config_writeb(proxy->vdev, addr, val);
  196 +}
  197 +
  198 +static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
  199 +{
  200 + VirtIOPCIProxy *proxy = opaque;
  201 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  202 + virtio_config_writew(proxy->vdev, addr, val);
  203 +}
  204 +
  205 +static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
  206 +{
  207 + VirtIOPCIProxy *proxy = opaque;
  208 + addr -= proxy->addr + VIRTIO_PCI_CONFIG;
  209 + virtio_config_writel(proxy->vdev, addr, val);
  210 +}
  211 +
  212 +static void virtio_map(PCIDevice *pci_dev, int region_num,
  213 + uint32_t addr, uint32_t size, int type)
  214 +{
  215 + VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
  216 + VirtIODevice *vdev = proxy->vdev;
  217 + int i;
  218 +
  219 + proxy->addr = addr;
  220 + for (i = 0; i < 3; i++) {
  221 + register_ioport_write(addr, VIRTIO_PCI_CONFIG, 1 << i,
  222 + virtio_ioport_write, proxy);
  223 + register_ioport_read(addr, VIRTIO_PCI_CONFIG, 1 << i,
  224 + virtio_ioport_read, proxy);
  225 + }
  226 +
  227 + if (vdev->config_len) {
  228 + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
  229 + virtio_pci_config_writeb, proxy);
  230 + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
  231 + virtio_pci_config_writew, proxy);
  232 + register_ioport_write(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
  233 + virtio_pci_config_writel, proxy);
  234 + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 1,
  235 + virtio_pci_config_readb, proxy);
  236 + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 2,
  237 + virtio_pci_config_readw, proxy);
  238 + register_ioport_read(addr + VIRTIO_PCI_CONFIG, vdev->config_len, 4,
  239 + virtio_pci_config_readl, proxy);
  240 +
  241 + vdev->get_config(vdev, vdev->config);
  242 + }
  243 +}
  244 +
  245 +static const VirtIOBindings virtio_pci_bindings = {
  246 + .update_irq = virtio_pci_update_irq
  247 +};
  248 +
  249 +static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
  250 + uint16_t vendor, uint16_t device,
  251 + uint16_t class_code, uint8_t pif)
  252 +{
  253 + uint8_t *config;
  254 + uint32_t size;
  255 +
  256 + proxy->vdev = vdev;
  257 +
  258 + config = proxy->pci_dev.config;
  259 + pci_config_set_vendor_id(config, vendor);
  260 + pci_config_set_device_id(config, device);
  261 +
  262 + config[0x08] = VIRTIO_PCI_ABI_VERSION;
  263 +
  264 + config[0x09] = pif;
  265 + pci_config_set_class(config, class_code);
  266 + config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
  267 +
  268 + config[0x2c] = vendor & 0xFF;
  269 + config[0x2d] = (vendor >> 8) & 0xFF;
  270 + config[0x2e] = vdev->device_id & 0xFF;
  271 + config[0x2f] = (vdev->device_id >> 8) & 0xFF;
  272 +
  273 + config[0x3d] = 1;
  274 +
  275 + size = 20 + vdev->config_len;
  276 + if (size & (size-1))
  277 + size = 1 << qemu_fls(size);
  278 +
  279 + pci_register_io_region(&proxy->pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
  280 + virtio_map);
  281 +
  282 + virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
  283 +}
  284 +
  285 +static void virtio_blk_init_pci(PCIDevice *pci_dev)
  286 +{
  287 + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
  288 + VirtIODevice *vdev;
  289 +
  290 + vdev = virtio_blk_init(&pci_dev->qdev);
  291 + virtio_init_pci(proxy, vdev,
  292 + PCI_VENDOR_ID_REDHAT_QUMRANET,
  293 + PCI_DEVICE_ID_VIRTIO_BLOCK,
  294 + PCI_CLASS_STORAGE_OTHER,
  295 + 0x00);
  296 +}
  297 +
  298 +static void virtio_console_init_pci(PCIDevice *pci_dev)
  299 +{
  300 + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
  301 + VirtIODevice *vdev;
  302 +
  303 + vdev = virtio_console_init(&pci_dev->qdev);
  304 + virtio_init_pci(proxy, vdev,
  305 + PCI_VENDOR_ID_REDHAT_QUMRANET,
  306 + PCI_DEVICE_ID_VIRTIO_CONSOLE,
  307 + PCI_CLASS_DISPLAY_OTHER,
  308 + 0x00);
  309 +}
  310 +
  311 +static void virtio_net_init_pci(PCIDevice *pci_dev)
  312 +{
  313 + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
  314 + VirtIODevice *vdev;
  315 +
  316 + vdev = virtio_net_init(&pci_dev->qdev);
  317 + virtio_init_pci(proxy, vdev,
  318 + PCI_VENDOR_ID_REDHAT_QUMRANET,
  319 + PCI_DEVICE_ID_VIRTIO_NET,
  320 + PCI_CLASS_NETWORK_ETHERNET,
  321 + 0x00);
  322 +}
  323 +
  324 +static void virtio_balloon_init_pci(PCIDevice *pci_dev)
  325 +{
  326 + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
  327 + VirtIODevice *vdev;
  328 +
  329 + vdev = virtio_balloon_init(&pci_dev->qdev);
  330 + virtio_init_pci(proxy, vdev,
  331 + PCI_VENDOR_ID_REDHAT_QUMRANET,
  332 + PCI_DEVICE_ID_VIRTIO_BALLOON,
  333 + PCI_CLASS_MEMORY_RAM,
  334 + 0x00);
  335 +}
  336 +
  337 +static void virtio_pci_register_devices(void)
  338 +{
  339 + pci_qdev_register("virtio-blk-pci", sizeof(VirtIOPCIProxy),
  340 + virtio_blk_init_pci);
  341 + pci_qdev_register("virtio-net-pci", sizeof(VirtIOPCIProxy),
  342 + virtio_net_init_pci);
  343 + pci_qdev_register("virtio-console-pci", sizeof(VirtIOPCIProxy),
  344 + virtio_console_init_pci);
  345 + pci_qdev_register("virtio-balloon-pci", sizeof(VirtIOPCIProxy),
  346 + virtio_balloon_init_pci);
  347 +}
  348 +
  349 +device_init(virtio_pci_register_devices)
... ...
hw/virtio.c
... ... @@ -16,43 +16,6 @@
16 16 #include "virtio.h"
17 17 #include "sysemu.h"
18 18  
19   -/* from Linux's linux/virtio_pci.h */
20   -
21   -/* A 32-bit r/o bitmask of the features supported by the host */
22   -#define VIRTIO_PCI_HOST_FEATURES 0
23   -
24   -/* A 32-bit r/w bitmask of features activated by the guest */
25   -#define VIRTIO_PCI_GUEST_FEATURES 4
26   -
27   -/* A 32-bit r/w PFN for the currently selected queue */
28   -#define VIRTIO_PCI_QUEUE_PFN 8
29   -
30   -/* A 16-bit r/o queue size for the currently selected queue */
31   -#define VIRTIO_PCI_QUEUE_NUM 12
32   -
33   -/* A 16-bit r/w queue selector */
34   -#define VIRTIO_PCI_QUEUE_SEL 14
35   -
36   -/* A 16-bit r/w queue notifier */
37   -#define VIRTIO_PCI_QUEUE_NOTIFY 16
38   -
39   -/* An 8-bit device status register. */
40   -#define VIRTIO_PCI_STATUS 18
41   -
42   -/* An 8-bit r/o interrupt status register. Reading the value will return the
43   - * current contents of the ISR and will also clear it. This is effectively
44   - * a read-and-acknowledge. */
45   -#define VIRTIO_PCI_ISR 19
46   -
47   -#define VIRTIO_PCI_CONFIG 20
48   -
49   -/* Virtio ABI version, if we increment this, we break the guest driver. */
50   -#define VIRTIO_PCI_ABI_VERSION 0
51   -
52   -/* How many bits to shift physical queue address written to QUEUE_PFN.
53   - * 12 is historical, and due to x86 page size. */
54   -#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
55   -
56 19 /* The alignment to use between consumer and producer parts of vring.
57 20 * x86 pagesize again. */
58 21 #define VIRTIO_PCI_VRING_ALIGN 4096
... ... @@ -102,7 +65,7 @@ typedef struct VRing
102 65 struct VirtQueue
103 66 {
104 67 VRing vring;
105   - uint32_t pfn;
  68 + target_phys_addr_t pa;
106 69 uint16_t last_avail_idx;
107 70 int inuse;
108 71 void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
... ... @@ -111,8 +74,10 @@ struct VirtQueue
111 74 #define VIRTIO_PCI_QUEUE_MAX 16
112 75  
113 76 /* virt queue functions */
114   -static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
  77 +static void virtqueue_init(VirtQueue *vq)
115 78 {
  79 + target_phys_addr_t pa = vq->pa;
  80 +
116 81 vq->vring.desc = pa;
117 82 vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
118 83 vq->vring.used = vring_align(vq->vring.avail +
... ... @@ -409,17 +374,14 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
409 374  
410 375 /* virtio device */
411 376  
412   -static VirtIODevice *to_virtio_device(PCIDevice *pci_dev)
  377 +void virtio_update_irq(VirtIODevice *vdev)
413 378 {
414   - return (VirtIODevice *)pci_dev;
415   -}
416   -
417   -static void virtio_update_irq(VirtIODevice *vdev)
418   -{
419   - qemu_set_irq(vdev->pci_dev.irq[0], vdev->isr & 1);
  379 + if (vdev->binding->update_irq) {
  380 + vdev->binding->update_irq(vdev->binding_opaque);
  381 + }
420 382 }
421 383  
422   -static void virtio_reset(void *opaque)
  384 +void virtio_reset(void *opaque)
423 385 {
424 386 VirtIODevice *vdev = opaque;
425 387 int i;
... ... @@ -438,103 +400,16 @@ static void virtio_reset(void *opaque)
438 400 vdev->vq[i].vring.avail = 0;
439 401 vdev->vq[i].vring.used = 0;
440 402 vdev->vq[i].last_avail_idx = 0;
441   - vdev->vq[i].pfn = 0;
  403 + vdev->vq[i].pa = 0;
442 404 }
443 405 }
444 406  
445   -static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
446   -{
447   - VirtIODevice *vdev = to_virtio_device(opaque);
448   - ram_addr_t pa;
449   -
450   - addr -= vdev->addr;
451   -
452   - switch (addr) {
453   - case VIRTIO_PCI_GUEST_FEATURES:
454   - /* Guest does not negotiate properly? We have to assume nothing. */
455   - if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
456   - if (vdev->bad_features)
457   - val = vdev->bad_features(vdev);
458   - else
459   - val = 0;
460   - }
461   - if (vdev->set_features)
462   - vdev->set_features(vdev, val);
463   - vdev->features = val;
464   - break;
465   - case VIRTIO_PCI_QUEUE_PFN:
466   - pa = (ram_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
467   - vdev->vq[vdev->queue_sel].pfn = val;
468   - if (pa == 0) {
469   - virtio_reset(vdev);
470   - } else {
471   - virtqueue_init(&vdev->vq[vdev->queue_sel], pa);
472   - }
473   - break;
474   - case VIRTIO_PCI_QUEUE_SEL:
475   - if (val < VIRTIO_PCI_QUEUE_MAX)
476   - vdev->queue_sel = val;
477   - break;
478   - case VIRTIO_PCI_QUEUE_NOTIFY:
479   - if (val < VIRTIO_PCI_QUEUE_MAX && vdev->vq[val].vring.desc)
480   - vdev->vq[val].handle_output(vdev, &vdev->vq[val]);
481   - break;
482   - case VIRTIO_PCI_STATUS:
483   - vdev->status = val & 0xFF;
484   - if (vdev->status == 0)
485   - virtio_reset(vdev);
486   - break;
487   - }
488   -}
489   -
490   -static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
491   -{
492   - VirtIODevice *vdev = to_virtio_device(opaque);
493   - uint32_t ret = 0xFFFFFFFF;
494   -
495   - addr -= vdev->addr;
496   -
497   - switch (addr) {
498   - case VIRTIO_PCI_HOST_FEATURES:
499   - ret = vdev->get_features(vdev);
500   - ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
501   - break;
502   - case VIRTIO_PCI_GUEST_FEATURES:
503   - ret = vdev->features;
504   - break;
505   - case VIRTIO_PCI_QUEUE_PFN:
506   - ret = vdev->vq[vdev->queue_sel].pfn;
507   - break;
508   - case VIRTIO_PCI_QUEUE_NUM:
509   - ret = vdev->vq[vdev->queue_sel].vring.num;
510   - break;
511   - case VIRTIO_PCI_QUEUE_SEL:
512   - ret = vdev->queue_sel;
513   - break;
514   - case VIRTIO_PCI_STATUS:
515   - ret = vdev->status;
516   - break;
517   - case VIRTIO_PCI_ISR:
518   - /* reading from the ISR also clears it. */
519   - ret = vdev->isr;
520   - vdev->isr = 0;
521   - virtio_update_irq(vdev);
522   - break;
523   - default:
524   - break;
525   - }
526   -
527   - return ret;
528   -}
529   -
530   -static uint32_t virtio_config_readb(void *opaque, uint32_t addr)
  407 +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr)
531 408 {
532   - VirtIODevice *vdev = opaque;
533 409 uint8_t val;
534 410  
535 411 vdev->get_config(vdev, vdev->config);
536 412  
537   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
538 413 if (addr > (vdev->config_len - sizeof(val)))
539 414 return (uint32_t)-1;
540 415  
... ... @@ -542,14 +417,12 @@ static uint32_t virtio_config_readb(void *opaque, uint32_t addr)
542 417 return val;
543 418 }
544 419  
545   -static uint32_t virtio_config_readw(void *opaque, uint32_t addr)
  420 +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr)
546 421 {
547   - VirtIODevice *vdev = opaque;
548 422 uint16_t val;
549 423  
550 424 vdev->get_config(vdev, vdev->config);
551 425  
552   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
553 426 if (addr > (vdev->config_len - sizeof(val)))
554 427 return (uint32_t)-1;
555 428  
... ... @@ -557,14 +430,12 @@ static uint32_t virtio_config_readw(void *opaque, uint32_t addr)
557 430 return val;
558 431 }
559 432  
560   -static uint32_t virtio_config_readl(void *opaque, uint32_t addr)
  433 +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr)
561 434 {
562   - VirtIODevice *vdev = opaque;
563 435 uint32_t val;
564 436  
565 437 vdev->get_config(vdev, vdev->config);
566 438  
567   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
568 439 if (addr > (vdev->config_len - sizeof(val)))
569 440 return (uint32_t)-1;
570 441  
... ... @@ -572,12 +443,10 @@ static uint32_t virtio_config_readl(void *opaque, uint32_t addr)
572 443 return val;
573 444 }
574 445  
575   -static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data)
  446 +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data)
576 447 {
577   - VirtIODevice *vdev = opaque;
578 448 uint8_t val = data;
579 449  
580   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
581 450 if (addr > (vdev->config_len - sizeof(val)))
582 451 return;
583 452  
... ... @@ -587,12 +456,10 @@ static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data)
587 456 vdev->set_config(vdev, vdev->config);
588 457 }
589 458  
590   -static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data)
  459 +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data)
591 460 {
592   - VirtIODevice *vdev = opaque;
593 461 uint16_t val = data;
594 462  
595   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
596 463 if (addr > (vdev->config_len - sizeof(val)))
597 464 return;
598 465  
... ... @@ -602,12 +469,10 @@ static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data)
602 469 vdev->set_config(vdev, vdev->config);
603 470 }
604 471  
605   -static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data)
  472 +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data)
606 473 {
607   - VirtIODevice *vdev = opaque;
608 474 uint32_t val = data;
609 475  
610   - addr -= vdev->addr + VIRTIO_PCI_CONFIG;
611 476 if (addr > (vdev->config_len - sizeof(val)))
612 477 return;
613 478  
... ... @@ -617,33 +482,30 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data)
617 482 vdev->set_config(vdev, vdev->config);
618 483 }
619 484  
620   -static void virtio_map(PCIDevice *pci_dev, int region_num,
621   - uint32_t addr, uint32_t size, int type)
  485 +void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr)
622 486 {
623   - VirtIODevice *vdev = to_virtio_device(pci_dev);
624   - int i;
625   -
626   - vdev->addr = addr;
627   - for (i = 0; i < 3; i++) {
628   - register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
629   - register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
  487 + if (addr == 0) {
  488 + virtio_reset(vdev);
  489 + } else {
  490 + vdev->vq[n].pa = addr;
  491 + virtqueue_init(&vdev->vq[n]);
630 492 }
  493 +}
  494 +
  495 +target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n)
  496 +{
  497 + return vdev->vq[n].pa;
  498 +}
  499 +
  500 +int virtio_queue_get_num(VirtIODevice *vdev, int n)
  501 +{
  502 + return vdev->vq[n].vring.num;
  503 +}
631 504  
632   - if (vdev->config_len) {
633   - register_ioport_write(addr + 20, vdev->config_len, 1,
634   - virtio_config_writeb, vdev);
635   - register_ioport_write(addr + 20, vdev->config_len, 2,
636   - virtio_config_writew, vdev);
637   - register_ioport_write(addr + 20, vdev->config_len, 4,
638   - virtio_config_writel, vdev);
639   - register_ioport_read(addr + 20, vdev->config_len, 1,
640   - virtio_config_readb, vdev);
641   - register_ioport_read(addr + 20, vdev->config_len, 2,
642   - virtio_config_readw, vdev);
643   - register_ioport_read(addr + 20, vdev->config_len, 4,
644   - virtio_config_readl, vdev);
645   -
646   - vdev->get_config(vdev, vdev->config);
  505 +void virtio_queue_notify(VirtIODevice *vdev, int n)
  506 +{
  507 + if (n < VIRTIO_PCI_QUEUE_MAX && vdev->vq[n].vring.desc) {
  508 + vdev->vq[n].handle_output(vdev, &vdev->vq[n]);
647 509 }
648 510 }
649 511  
... ... @@ -691,9 +553,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
691 553 {
692 554 int i;
693 555  
694   - pci_device_save(&vdev->pci_dev, f);
  556 + /* FIXME: load/save binding. */
  557 + //pci_device_save(&vdev->pci_dev, f);
695 558  
696   - qemu_put_be32s(f, &vdev->addr);
697 559 qemu_put_8s(f, &vdev->status);
698 560 qemu_put_8s(f, &vdev->isr);
699 561 qemu_put_be16s(f, &vdev->queue_sel);
... ... @@ -713,7 +575,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
713 575 break;
714 576  
715 577 qemu_put_be32(f, vdev->vq[i].vring.num);
716   - qemu_put_be32s(f, &vdev->vq[i].pfn);
  578 + qemu_put_be64(f, vdev->vq[i].pa);
717 579 qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
718 580 }
719 581 }
... ... @@ -722,9 +584,9 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
722 584 {
723 585 int num, i;
724 586  
725   - pci_device_load(&vdev->pci_dev, f);
  587 + /* FIXME: load/save binding. */
  588 + //pci_device_load(&vdev->pci_dev, f);
726 589  
727   - qemu_get_be32s(f, &vdev->addr);
728 590 qemu_get_8s(f, &vdev->status);
729 591 qemu_get_8s(f, &vdev->isr);
730 592 qemu_get_be16s(f, &vdev->queue_sel);
... ... @@ -736,14 +598,11 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
736 598  
737 599 for (i = 0; i < num; i++) {
738 600 vdev->vq[i].vring.num = qemu_get_be32(f);
739   - qemu_get_be32s(f, &vdev->vq[i].pfn);
  601 + vdev->vq[i].pa = qemu_get_be64(f);
740 602 qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
741 603  
742   - if (vdev->vq[i].pfn) {
743   - target_phys_addr_t pa;
744   -
745   - pa = (ram_addr_t)vdev->vq[i].pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
746   - virtqueue_init(&vdev->vq[i], pa);
  604 + if (vdev->vq[i].pa) {
  605 + virtqueue_init(&vdev->vq[i]);
747 606 }
748 607 }
749 608  
... ... @@ -757,40 +616,19 @@ void virtio_cleanup(VirtIODevice *vdev)
757 616 qemu_free(vdev->vq);
758 617 }
759 618  
760   -VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name,
761   - uint16_t vendor, uint16_t device,
762   - uint16_t subvendor, uint16_t subdevice,
763   - uint16_t class_code, uint8_t pif,
764   - size_t config_size)
  619 +VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
  620 + size_t config_size, size_t struct_size)
765 621 {
766 622 VirtIODevice *vdev;
767   - uint8_t *config;
768   - uint32_t size;
769 623  
770   - vdev = to_virtio_device(pci_dev);
  624 + vdev = qemu_mallocz(struct_size);
771 625  
  626 + vdev->device_id = device_id;
772 627 vdev->status = 0;
773 628 vdev->isr = 0;
774 629 vdev->queue_sel = 0;
775 630 vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
776 631  
777   - config = pci_dev->config;
778   - pci_config_set_vendor_id(config, vendor);
779   - pci_config_set_device_id(config, device);
780   -
781   - config[0x08] = VIRTIO_PCI_ABI_VERSION;
782   -
783   - config[0x09] = pif;
784   - pci_config_set_class(config, class_code);
785   - config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
786   -
787   - config[0x2c] = subvendor & 0xFF;
788   - config[0x2d] = (subvendor >> 8) & 0xFF;
789   - config[0x2e] = subdevice & 0xFF;
790   - config[0x2f] = (subdevice >> 8) & 0xFF;
791   -
792   - config[0x3d] = 1;
793   -
794 632 vdev->name = name;
795 633 vdev->config_len = config_size;
796 634 if (vdev->config_len)
... ... @@ -798,13 +636,13 @@ VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name,
798 636 else
799 637 vdev->config = NULL;
800 638  
801   - size = 20 + config_size;
802   - if (size & (size-1))
803   - size = 1 << qemu_fls(size);
804   -
805   - pci_register_io_region(pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
806   - virtio_map);
807 639 qemu_register_reset(virtio_reset, vdev);
808   -
809 640 return vdev;
810 641 }
  642 +
  643 +void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
  644 + void *opaque)
  645 +{
  646 + vdev->binding = binding;
  647 + vdev->binding_opaque = opaque;
  648 +}
... ...
hw/virtio.h
... ... @@ -15,7 +15,7 @@
15 15 #define _QEMU_VIRTIO_H
16 16  
17 17 #include "hw.h"
18   -#include "pci.h"
  18 +#include "qdev.h"
19 19  
20 20 /* from Linux's linux/virtio_config.h */
21 21  
... ... @@ -70,13 +70,15 @@ typedef struct VirtQueueElement
70 70 struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
71 71 } VirtQueueElement;
72 72  
  73 +typedef struct {
  74 + void (*update_irq)(void * opaque);
  75 +} VirtIOBindings;
  76 +
73 77 #define VIRTIO_PCI_QUEUE_MAX 16
74 78  
75 79 struct VirtIODevice
76 80 {
77   - PCIDevice pci_dev;
78 81 const char *name;
79   - uint32_t addr;
80 82 uint8_t status;
81 83 uint8_t isr;
82 84 uint16_t queue_sel;
... ... @@ -90,14 +92,11 @@ struct VirtIODevice
90 92 void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
91 93 void (*reset)(VirtIODevice *vdev);
92 94 VirtQueue *vq;
  95 + const VirtIOBindings *binding;
  96 + void *binding_opaque;
  97 + uint16_t device_id;
93 98 };
94 99  
95   -VirtIODevice *virtio_init_pci(PCIDevice *pci_dev, const char *name,
96   - uint16_t vendor, uint16_t device,
97   - uint16_t subvendor, uint16_t subdevice,
98   - uint16_t class_code, uint8_t pif,
99   - size_t config_size);
100   -
101 100 VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
102 101 void (*handle_output)(VirtIODevice *,
103 102 VirtQueue *));
... ... @@ -127,4 +126,30 @@ int virtio_queue_ready(VirtQueue *vq);
127 126  
128 127 int virtio_queue_empty(VirtQueue *vq);
129 128  
  129 +/* Host binding interface. */
  130 +
  131 +VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
  132 + size_t config_size, size_t struct_size);
  133 +uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr);
  134 +uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr);
  135 +uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr);
  136 +void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data);
  137 +void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data);
  138 +void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data);
  139 +void virtio_queue_set_addr(VirtIODevice *vdev, int n, target_phys_addr_t addr);
  140 +target_phys_addr_t virtio_queue_get_addr(VirtIODevice *vdev, int n);
  141 +int virtio_queue_get_num(VirtIODevice *vdev, int n);
  142 +void virtio_queue_notify(VirtIODevice *vdev, int n);
  143 +void virtio_reset(void *opaque);
  144 +void virtio_update_irq(VirtIODevice *vdev);
  145 +
  146 +void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
  147 + void *opaque);
  148 +
  149 +/* Base devices. */
  150 +VirtIODevice *virtio_blk_init(DeviceState *dev);
  151 +VirtIODevice *virtio_net_init(DeviceState *dev);
  152 +VirtIODevice *virtio_console_init(DeviceState *dev);
  153 +VirtIODevice *virtio_balloon_init(DeviceState *dev);
  154 +
130 155 #endif
... ...