Commit 340d96e7ce6e1c2e6d75504e9b4d8153896d5b42

Authored by Paul Brook
1 parent 53c25cea

Syborg virtio bindings.

Implement Syborg device bindings for virtio-net.

Signed-off-by: Paul Brook <paul@codesourcery.com>
Makefile.target
... ... @@ -658,6 +658,7 @@ OBJS+= musicpal.o pflash_cfi02.o
658 658 OBJS+= framebuffer.o
659 659 OBJS+= syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
660 660 OBJS+= syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
  661 +OBJS+= syborg_virtio.o
661 662 CPPFLAGS += -DHAS_AUDIO
662 663 endif
663 664 ifeq ($(TARGET_BASE_ARCH), sh4)
... ...
hw/syborg.c
... ... @@ -26,6 +26,7 @@
26 26 #include "boards.h"
27 27 #include "arm-misc.h"
28 28 #include "sysemu.h"
  29 +#include "net.h"
29 30  
30 31 static struct arm_boot_info syborg_binfo;
31 32  
... ... @@ -76,6 +77,19 @@ static void syborg_init(ram_addr_t ram_size,
76 77 sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]);
77 78 sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]);
78 79  
  80 + if (nd_table[0].vlan) {
  81 + DeviceState *dev;
  82 + SysBusDevice *s;
  83 +
  84 + qemu_check_nic_model(&nd_table[0], "virtio");
  85 + dev = qdev_create(NULL, "syborg,virtio-net");
  86 + qdev_set_netdev(dev, &nd_table[0]);
  87 + qdev_init(dev);
  88 + s = sysbus_from_qdev(dev);
  89 + sysbus_mmio_map(s, 0, 0xc000c000);
  90 + sysbus_connect_irq(s, 0, pic[9]);
  91 + }
  92 +
79 93 syborg_binfo.ram_size = ram_size;
80 94 syborg_binfo.kernel_filename = kernel_filename;
81 95 syborg_binfo.kernel_cmdline = kernel_cmdline;
... ...
hw/syborg_virtio.c 0 → 100644
  1 +/*
  2 + * Virtio Syborg bindings
  3 + *
  4 + * Copyright (c) 2009 CodeSourcery
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +#include "syborg.h"
  26 +#include "sysbus.h"
  27 +#include "virtio.h"
  28 +#include "sysemu.h"
  29 +
  30 +//#define DEBUG_SYBORG_VIRTIO
  31 +
  32 +#ifdef DEBUG_SYBORG_VIRTIO
  33 +#define DPRINTF(fmt, ...) \
  34 +do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0)
  35 +#define BADF(fmt, ...) \
  36 +do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__); \
  37 + exit(1);} while (0)
  38 +#else
  39 +#define DPRINTF(fmt, ...) do {} while(0)
  40 +#define BADF(fmt, ...) \
  41 +do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0)
  42 +#endif
  43 +
  44 +enum {
  45 + SYBORG_VIRTIO_ID = 0,
  46 + SYBORG_VIRTIO_DEVTYPE = 1,
  47 + SYBORG_VIRTIO_HOST_FEATURES = 2,
  48 + SYBORG_VIRTIO_GUEST_FEATURES = 3,
  49 + SYBORG_VIRTIO_QUEUE_BASE = 4,
  50 + SYBORG_VIRTIO_QUEUE_NUM = 5,
  51 + SYBORG_VIRTIO_QUEUE_SEL = 6,
  52 + SYBORG_VIRTIO_QUEUE_NOTIFY = 7,
  53 + SYBORG_VIRTIO_STATUS = 8,
  54 + SYBORG_VIRTIO_INT_ENABLE = 9,
  55 + SYBORG_VIRTIO_INT_STATUS = 10
  56 +};
  57 +
  58 +#define SYBORG_VIRTIO_CONFIG 0x100
  59 +
  60 +/* Device independent interface. */
  61 +
  62 +typedef struct {
  63 + SysBusDevice busdev;
  64 + VirtIODevice *vdev;
  65 + qemu_irq irq;
  66 + uint32_t int_enable;
  67 + uint32_t id;
  68 +} SyborgVirtIOProxy;
  69 +
  70 +static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
  71 +{
  72 + SyborgVirtIOProxy *s = opaque;
  73 + VirtIODevice *vdev = s->vdev;
  74 + uint32_t ret;
  75 +
  76 + DPRINTF("readl 0x%x\n", (int)offset);
  77 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  78 + return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
  79 + }
  80 + switch(offset >> 2) {
  81 + case SYBORG_VIRTIO_ID:
  82 + ret = SYBORG_ID_VIRTIO;
  83 + break;
  84 + case SYBORG_VIRTIO_DEVTYPE:
  85 + ret = s->id;
  86 + break;
  87 + case SYBORG_VIRTIO_HOST_FEATURES:
  88 + ret = vdev->get_features(vdev);
  89 + ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
  90 + break;
  91 + case SYBORG_VIRTIO_GUEST_FEATURES:
  92 + ret = vdev->features;
  93 + break;
  94 + case SYBORG_VIRTIO_QUEUE_BASE:
  95 + ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
  96 + break;
  97 + case SYBORG_VIRTIO_QUEUE_NUM:
  98 + ret = virtio_queue_get_num(vdev, vdev->queue_sel);
  99 + break;
  100 + case SYBORG_VIRTIO_QUEUE_SEL:
  101 + ret = vdev->queue_sel;
  102 + break;
  103 + case SYBORG_VIRTIO_STATUS:
  104 + ret = vdev->status;
  105 + break;
  106 + case SYBORG_VIRTIO_INT_ENABLE:
  107 + ret = s->int_enable;
  108 + break;
  109 + case SYBORG_VIRTIO_INT_STATUS:
  110 + ret = vdev->isr;
  111 + break;
  112 + default:
  113 + BADF("Bad read offset 0x%x\n", (int)offset);
  114 + return 0;
  115 + }
  116 + return ret;
  117 +}
  118 +
  119 +static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
  120 + uint32_t value)
  121 +{
  122 + SyborgVirtIOProxy *s = opaque;
  123 + VirtIODevice *vdev = s->vdev;
  124 +
  125 + DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
  126 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  127 + return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
  128 + value);
  129 + }
  130 + switch (offset >> 2) {
  131 + case SYBORG_VIRTIO_GUEST_FEATURES:
  132 + if (vdev->set_features)
  133 + vdev->set_features(vdev, value);
  134 + vdev->features = value;
  135 + break;
  136 + case SYBORG_VIRTIO_QUEUE_BASE:
  137 + virtio_queue_set_addr(vdev, vdev->queue_sel, value);
  138 + break;
  139 + case SYBORG_VIRTIO_QUEUE_SEL:
  140 + if (value < VIRTIO_PCI_QUEUE_MAX)
  141 + vdev->queue_sel = value;
  142 + break;
  143 + case SYBORG_VIRTIO_QUEUE_NOTIFY:
  144 + virtio_queue_notify(vdev, value);
  145 + break;
  146 + case SYBORG_VIRTIO_STATUS:
  147 + vdev->status = value & 0xFF;
  148 + if (vdev->status == 0)
  149 + virtio_reset(vdev);
  150 + break;
  151 + case SYBORG_VIRTIO_INT_ENABLE:
  152 + s->int_enable = value;
  153 + virtio_update_irq(vdev);
  154 + break;
  155 + case SYBORG_VIRTIO_INT_STATUS:
  156 + vdev->isr &= ~value;
  157 + virtio_update_irq(vdev);
  158 + break;
  159 + default:
  160 + BADF("Bad write offset 0x%x\n", (int)offset);
  161 + break;
  162 + }
  163 +}
  164 +
  165 +static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
  166 +{
  167 + SyborgVirtIOProxy *s = opaque;
  168 + VirtIODevice *vdev = s->vdev;
  169 +
  170 + DPRINTF("readw 0x%x\n", (int)offset);
  171 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  172 + return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
  173 + }
  174 + BADF("Bad halfword read offset 0x%x\n", (int)offset);
  175 + return -1;
  176 +}
  177 +
  178 +static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
  179 + uint32_t value)
  180 +{
  181 + SyborgVirtIOProxy *s = opaque;
  182 + VirtIODevice *vdev = s->vdev;
  183 +
  184 + DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
  185 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  186 + return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
  187 + value);
  188 + }
  189 + BADF("Bad halfword write offset 0x%x\n", (int)offset);
  190 +}
  191 +
  192 +static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
  193 +{
  194 + SyborgVirtIOProxy *s = opaque;
  195 + VirtIODevice *vdev = s->vdev;
  196 +
  197 + DPRINTF("readb 0x%x\n", (int)offset);
  198 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  199 + return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
  200 + }
  201 + BADF("Bad byte read offset 0x%x\n", (int)offset);
  202 + return -1;
  203 +}
  204 +
  205 +static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
  206 + uint32_t value)
  207 +{
  208 + SyborgVirtIOProxy *s = opaque;
  209 + VirtIODevice *vdev = s->vdev;
  210 +
  211 + DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
  212 + if (offset >= SYBORG_VIRTIO_CONFIG) {
  213 + return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
  214 + value);
  215 + }
  216 + BADF("Bad byte write offset 0x%x\n", (int)offset);
  217 +}
  218 +
  219 +static CPUReadMemoryFunc *syborg_virtio_readfn[] = {
  220 + syborg_virtio_readb,
  221 + syborg_virtio_readw,
  222 + syborg_virtio_readl
  223 +};
  224 +
  225 +static CPUWriteMemoryFunc *syborg_virtio_writefn[] = {
  226 + syborg_virtio_writeb,
  227 + syborg_virtio_writew,
  228 + syborg_virtio_writel
  229 +};
  230 +
  231 +static void syborg_virtio_update_irq(void *opaque)
  232 +{
  233 + SyborgVirtIOProxy *proxy = opaque;
  234 + int level;
  235 +
  236 + level = proxy->int_enable & proxy->vdev->isr;
  237 + DPRINTF("IRQ %d\n", level);
  238 + qemu_set_irq(proxy->irq, level != 0);
  239 +}
  240 +
  241 +static VirtIOBindings syborg_virtio_bindings = {
  242 + .update_irq = syborg_virtio_update_irq
  243 +};
  244 +
  245 +static void syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
  246 +{
  247 + int iomemtype;
  248 +
  249 + proxy->vdev = vdev;
  250 +
  251 + sysbus_init_irq(&proxy->busdev, &proxy->irq);
  252 + iomemtype = cpu_register_io_memory(0, syborg_virtio_readfn,
  253 + syborg_virtio_writefn, proxy);
  254 + sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
  255 +
  256 + proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
  257 +
  258 + virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
  259 +}
  260 +
  261 +/* Device specific bindings. */
  262 +
  263 +static void syborg_virtio_net_init(SysBusDevice *dev)
  264 +{
  265 + VirtIODevice *vdev;
  266 + SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
  267 +
  268 + vdev = virtio_net_init(&dev->qdev);
  269 + syborg_virtio_init(proxy, vdev);
  270 +}
  271 +
  272 +static void syborg_virtio_register_devices(void)
  273 +{
  274 + sysbus_register_dev("syborg,virtio-net", sizeof(SyborgVirtIOProxy),
  275 + syborg_virtio_net_init);
  276 +}
  277 +
  278 +device_init(syborg_virtio_register_devices)
... ...