2 * Virtio Syborg bindings
4 * Copyright (c) 2009 CodeSourcery
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
30 //#define DEBUG_SYBORG_VIRTIO
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__); \
39 #define DPRINTF(fmt, ...) do {} while(0)
40 #define BADF(fmt, ...) \
41 do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (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
58 #define SYBORG_VIRTIO_CONFIG 0x100
60 /* Device independent interface. */
70 static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
72 SyborgVirtIOProxy *s = opaque;
73 VirtIODevice *vdev = s->vdev;
76 DPRINTF("readl 0x%x\n", (int)offset);
77 if (offset >= SYBORG_VIRTIO_CONFIG) {
78 return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
81 case SYBORG_VIRTIO_ID:
82 ret = SYBORG_ID_VIRTIO;
84 case SYBORG_VIRTIO_DEVTYPE:
87 case SYBORG_VIRTIO_HOST_FEATURES:
88 ret = vdev->get_features(vdev);
89 ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
91 case SYBORG_VIRTIO_GUEST_FEATURES:
94 case SYBORG_VIRTIO_QUEUE_BASE:
95 ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
97 case SYBORG_VIRTIO_QUEUE_NUM:
98 ret = virtio_queue_get_num(vdev, vdev->queue_sel);
100 case SYBORG_VIRTIO_QUEUE_SEL:
101 ret = vdev->queue_sel;
103 case SYBORG_VIRTIO_STATUS:
106 case SYBORG_VIRTIO_INT_ENABLE:
109 case SYBORG_VIRTIO_INT_STATUS:
113 BADF("Bad read offset 0x%x\n", (int)offset);
119 static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
122 SyborgVirtIOProxy *s = opaque;
123 VirtIODevice *vdev = s->vdev;
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,
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;
136 case SYBORG_VIRTIO_QUEUE_BASE:
137 virtio_queue_set_addr(vdev, vdev->queue_sel, value);
139 case SYBORG_VIRTIO_QUEUE_SEL:
140 if (value < VIRTIO_PCI_QUEUE_MAX)
141 vdev->queue_sel = value;
143 case SYBORG_VIRTIO_QUEUE_NOTIFY:
144 virtio_queue_notify(vdev, value);
146 case SYBORG_VIRTIO_STATUS:
147 vdev->status = value & 0xFF;
148 if (vdev->status == 0)
151 case SYBORG_VIRTIO_INT_ENABLE:
152 s->int_enable = value;
153 virtio_update_irq(vdev);
155 case SYBORG_VIRTIO_INT_STATUS:
157 virtio_update_irq(vdev);
160 BADF("Bad write offset 0x%x\n", (int)offset);
165 static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
167 SyborgVirtIOProxy *s = opaque;
168 VirtIODevice *vdev = s->vdev;
170 DPRINTF("readw 0x%x\n", (int)offset);
171 if (offset >= SYBORG_VIRTIO_CONFIG) {
172 return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
174 BADF("Bad halfword read offset 0x%x\n", (int)offset);
178 static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
181 SyborgVirtIOProxy *s = opaque;
182 VirtIODevice *vdev = s->vdev;
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,
189 BADF("Bad halfword write offset 0x%x\n", (int)offset);
192 static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
194 SyborgVirtIOProxy *s = opaque;
195 VirtIODevice *vdev = s->vdev;
197 DPRINTF("readb 0x%x\n", (int)offset);
198 if (offset >= SYBORG_VIRTIO_CONFIG) {
199 return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
201 BADF("Bad byte read offset 0x%x\n", (int)offset);
205 static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
208 SyborgVirtIOProxy *s = opaque;
209 VirtIODevice *vdev = s->vdev;
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,
216 BADF("Bad byte write offset 0x%x\n", (int)offset);
219 static CPUReadMemoryFunc *syborg_virtio_readfn[] = {
225 static CPUWriteMemoryFunc *syborg_virtio_writefn[] = {
226 syborg_virtio_writeb,
227 syborg_virtio_writew,
231 static void syborg_virtio_update_irq(void *opaque)
233 SyborgVirtIOProxy *proxy = opaque;
236 level = proxy->int_enable & proxy->vdev->isr;
237 DPRINTF("IRQ %d\n", level);
238 qemu_set_irq(proxy->irq, level != 0);
241 static VirtIOBindings syborg_virtio_bindings = {
242 .update_irq = syborg_virtio_update_irq
245 static void syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
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);
256 proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
258 virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
261 /* Device specific bindings. */
263 static void syborg_virtio_net_init(SysBusDevice *dev)
266 SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
268 vdev = virtio_net_init(&dev->qdev);
269 syborg_virtio_init(proxy, vdev);
272 static void syborg_virtio_register_devices(void)
274 sysbus_register_dev("syborg,virtio-net", sizeof(SyborgVirtIOProxy),
275 syborg_virtio_net_init);
278 device_init(syborg_virtio_register_devices)