Clean include statements
[qemu/ar7.git] / hw / arm / syborg_virtio.c
blobee64f9bf81277434f190c77f2061c0bfa1ee1ad1
1 /*
2 * Virtio Syborg bindings
4 * Copyright (c) 2009 CodeSourcery
5 * Copyright (c) 2010, 2013 Stefan Weil
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
26 #include "qemu/osdep.h"
27 #include "syborg.h"
28 #include "hw/sysbus.h"
29 #include "virtio.h"
30 #include "virtio-net.h"
32 //#define DEBUG_SYBORG_VIRTIO
34 #ifdef DEBUG_SYBORG_VIRTIO
35 #define DPRINTF(fmt, ...) \
36 do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0)
37 #define BADF(fmt, ...) \
38 do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__); \
39 exit(1);} while (0)
40 #else
41 #define DPRINTF(fmt, ...) do {} while(0)
42 #define BADF(fmt, ...) \
43 do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0)
44 #endif
46 enum {
47 SYBORG_VIRTIO_ID = 0,
48 SYBORG_VIRTIO_DEVTYPE = 1,
49 SYBORG_VIRTIO_HOST_FEATURES = 2,
50 SYBORG_VIRTIO_GUEST_FEATURES = 3,
51 SYBORG_VIRTIO_QUEUE_BASE = 4,
52 SYBORG_VIRTIO_QUEUE_NUM = 5,
53 SYBORG_VIRTIO_QUEUE_SEL = 6,
54 SYBORG_VIRTIO_QUEUE_NOTIFY = 7,
55 SYBORG_VIRTIO_STATUS = 8,
56 SYBORG_VIRTIO_INT_ENABLE = 9,
57 SYBORG_VIRTIO_INT_STATUS = 10
60 #define SYBORG_VIRTIO_CONFIG 0x100
62 /* Device independent interface. */
64 typedef struct {
65 SysBusDevice busdev;
66 VirtIODevice *vdev;
67 MemoryRegion iomem;
68 qemu_irq irq;
69 uint32_t int_enable;
70 uint32_t id;
71 NICConf nic;
72 uint32_t host_features;
73 virtio_net_conf net;
74 } SyborgVirtIOProxy;
76 static SyborgVirtIOProxy *to_virtio_syborg_device(DeviceState *d)
78 return container_of(d, SyborgVirtIOProxy, busdev.qdev);
81 static uint32_t syborg_virtio_readl(void *opaque, hwaddr offset)
83 SyborgVirtIOProxy *s = opaque;
84 VirtIODevice *vdev = s->vdev;
85 uint32_t ret;
87 DPRINTF("readl 0x%x\n", (int)offset);
88 if (offset >= SYBORG_VIRTIO_CONFIG) {
89 return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
91 switch(offset >> 2) {
92 case SYBORG_VIRTIO_ID:
93 ret = SYBORG_ID_VIRTIO;
94 break;
95 case SYBORG_VIRTIO_DEVTYPE:
96 ret = s->id;
97 break;
98 case SYBORG_VIRTIO_HOST_FEATURES:
99 ret = s->host_features;
100 break;
101 case SYBORG_VIRTIO_GUEST_FEATURES:
102 ret = vdev->guest_features;
103 break;
104 case SYBORG_VIRTIO_QUEUE_BASE:
105 ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
106 break;
107 case SYBORG_VIRTIO_QUEUE_NUM:
108 ret = virtio_queue_get_num(vdev, vdev->queue_sel);
109 break;
110 case SYBORG_VIRTIO_QUEUE_SEL:
111 ret = vdev->queue_sel;
112 break;
113 case SYBORG_VIRTIO_STATUS:
114 ret = vdev->status;
115 break;
116 case SYBORG_VIRTIO_INT_ENABLE:
117 ret = s->int_enable;
118 break;
119 case SYBORG_VIRTIO_INT_STATUS:
120 ret = vdev->isr;
121 break;
122 default:
123 BADF("Bad read offset 0x%x\n", (int)offset);
124 return 0;
126 return ret;
129 static void syborg_virtio_writel(void *opaque, hwaddr offset,
130 uint32_t value)
132 SyborgVirtIOProxy *s = opaque;
133 VirtIODevice *vdev = s->vdev;
135 DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
136 if (offset >= SYBORG_VIRTIO_CONFIG) {
137 return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
138 value);
140 switch (offset >> 2) {
141 case SYBORG_VIRTIO_GUEST_FEATURES:
142 virtio_set_features(vdev, value);
143 break;
144 case SYBORG_VIRTIO_QUEUE_BASE:
145 if (value == 0)
146 virtio_reset(vdev);
147 else
148 virtio_queue_set_addr(vdev, vdev->queue_sel, value);
149 break;
150 case SYBORG_VIRTIO_QUEUE_SEL:
151 if (value < VIRTIO_PCI_QUEUE_MAX)
152 vdev->queue_sel = value;
153 break;
154 case SYBORG_VIRTIO_QUEUE_NOTIFY:
155 if (value < VIRTIO_PCI_QUEUE_MAX) {
156 virtio_queue_notify(vdev, value);
158 break;
159 case SYBORG_VIRTIO_STATUS:
160 virtio_set_status(vdev, value & 0xFF);
161 if (vdev->status == 0)
162 virtio_reset(vdev);
163 break;
164 case SYBORG_VIRTIO_INT_ENABLE:
165 s->int_enable = value;
166 virtio_update_irq(vdev);
167 break;
168 case SYBORG_VIRTIO_INT_STATUS:
169 vdev->isr &= ~value;
170 virtio_update_irq(vdev);
171 break;
172 default:
173 BADF("Bad write offset 0x%x\n", (int)offset);
174 break;
178 static uint32_t syborg_virtio_readw(void *opaque, hwaddr offset)
180 SyborgVirtIOProxy *s = opaque;
181 VirtIODevice *vdev = s->vdev;
183 DPRINTF("readw 0x%x\n", (int)offset);
184 if (offset >= SYBORG_VIRTIO_CONFIG) {
185 return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
187 BADF("Bad halfword read offset 0x%x\n", (int)offset);
188 return -1;
191 static void syborg_virtio_writew(void *opaque, hwaddr offset,
192 uint32_t value)
194 SyborgVirtIOProxy *s = opaque;
195 VirtIODevice *vdev = s->vdev;
197 DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
198 if (offset >= SYBORG_VIRTIO_CONFIG) {
199 return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
200 value);
202 BADF("Bad halfword write offset 0x%x\n", (int)offset);
205 static uint32_t syborg_virtio_readb(void *opaque, hwaddr offset)
207 SyborgVirtIOProxy *s = opaque;
208 VirtIODevice *vdev = s->vdev;
210 DPRINTF("readb 0x%x\n", (int)offset);
211 if (offset >= SYBORG_VIRTIO_CONFIG) {
212 return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
214 BADF("Bad byte read offset 0x%x\n", (int)offset);
215 return -1;
218 static void syborg_virtio_writeb(void *opaque, hwaddr offset,
219 uint32_t value)
221 SyborgVirtIOProxy *s = opaque;
222 VirtIODevice *vdev = s->vdev;
224 DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
225 if (offset >= SYBORG_VIRTIO_CONFIG) {
226 return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
227 value);
229 BADF("Bad byte write offset 0x%x\n", (int)offset);
232 static const MemoryRegionOps syborg_virtio_ops = {
233 .old_mmio = {
234 .read = { syborg_virtio_readb, syborg_virtio_readw, syborg_virtio_readl },
235 .write = { syborg_virtio_writeb, syborg_virtio_writew, syborg_virtio_writel },
237 .endianness = DEVICE_NATIVE_ENDIAN,
240 static void syborg_virtio_update_irq(DeviceState *d, uint16_t vector)
242 SyborgVirtIOProxy *proxy = to_virtio_syborg_device(d);
243 int level;
245 level = proxy->int_enable & proxy->vdev->isr;
246 DPRINTF("IRQ %d\n", level);
247 qemu_set_irq(proxy->irq, level != 0);
250 static unsigned syborg_virtio_get_features(DeviceState *d)
252 SyborgVirtIOProxy *proxy = to_virtio_syborg_device(d);
253 return proxy->host_features;
256 static VirtIOBindings syborg_virtio_bindings = {
257 .notify = syborg_virtio_update_irq,
258 .get_features = syborg_virtio_get_features,
261 static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
263 proxy->vdev = vdev;
265 /* Don't support multiple vectors */
266 proxy->vdev->nvectors = 0;
267 sysbus_init_irq(&proxy->busdev, &proxy->irq);
268 memory_region_init_io(&proxy->iomem, &syborg_virtio_ops, proxy,
269 "virtio", 0x1000);
270 sysbus_init_mmio(&proxy->busdev, &proxy->iomem);
272 proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
274 qemu_register_reset(virtio_reset, vdev);
276 virtio_bind_device(vdev, &syborg_virtio_bindings, DEVICE(proxy));
277 proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
278 proxy->host_features = vdev->get_features(vdev, proxy->host_features);
279 return 0;
282 /* Device specific bindings. */
284 static int syborg_virtio_net_init(SysBusDevice *sbd)
286 VirtIODevice *vdev;
287 DeviceState *dev = DEVICE(sbd);
288 SyborgVirtIOProxy *proxy = SYBORG_VIRTIOPROXY(dev);
290 vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net,
291 proxy->host_features);
293 return syborg_virtio_init(proxy, vdev);
296 static Property syborg_virtio_net_properties[] = {
297 DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
298 DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
299 DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy,
300 net.txtimer, TX_TIMER_INTERVAL),
301 DEFINE_PROP_INT32("x-txburst", SyborgVirtIOProxy,
302 net.txburst, TX_BURST),
303 DEFINE_PROP_STRING("tx", SyborgVirtIOProxy, net.tx),
304 DEFINE_PROP_END_OF_LIST()
307 static void syborg_virtio_net_class_init(ObjectClass *klass, void *data)
309 DeviceClass *dc = DEVICE_CLASS(klass);
310 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
311 dc->props = syborg_virtio_net_properties;
312 k->init = syborg_virtio_net_init;
315 static const TypeInfo syborg_virtio_net_info = {
316 .name = "syborg,virtio-net",
317 .parent = TYPE_SYS_BUS_DEVICE,
318 .instance_size = sizeof(SyborgVirtIOProxy),
319 .class_init = syborg_virtio_net_class_init
322 static void syborg_virtio_register_types(void)
324 type_register_static(&syborg_virtio_net_info);
327 type_init(syborg_virtio_register_types)