]> git.proxmox.com Git - qemu.git/blame - hw/syborg_virtio.c
user: Restore debug usage message for '-d ?' in user mode emulation
[qemu.git] / hw / syborg_virtio.c
CommitLineData
340d96e7
PB
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"
8172539d 28#include "virtio-net.h"
340d96e7
PB
29
30//#define DEBUG_SYBORG_VIRTIO
31
32#ifdef DEBUG_SYBORG_VIRTIO
33#define DPRINTF(fmt, ...) \
34do { printf("syborg_virtio: " fmt , ## __VA_ARGS__); } while (0)
35#define BADF(fmt, ...) \
36do { 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, ...) \
41do { fprintf(stderr, "syborg_virtio: error: " fmt , ## __VA_ARGS__);} while (0)
42#endif
43
44enum {
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
62typedef struct {
63 SysBusDevice busdev;
64 VirtIODevice *vdev;
65 qemu_irq irq;
66 uint32_t int_enable;
67 uint32_t id;
97b15621 68 NICConf nic;
8172539d 69 uint32_t host_features;
f0c07c7c 70 virtio_net_conf net;
340d96e7
PB
71} SyborgVirtIOProxy;
72
c227f099 73static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
340d96e7
PB
74{
75 SyborgVirtIOProxy *s = opaque;
76 VirtIODevice *vdev = s->vdev;
77 uint32_t ret;
78
79 DPRINTF("readl 0x%x\n", (int)offset);
80 if (offset >= SYBORG_VIRTIO_CONFIG) {
81 return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
82 }
83 switch(offset >> 2) {
84 case SYBORG_VIRTIO_ID:
85 ret = SYBORG_ID_VIRTIO;
86 break;
87 case SYBORG_VIRTIO_DEVTYPE:
88 ret = s->id;
89 break;
90 case SYBORG_VIRTIO_HOST_FEATURES:
8172539d 91 ret = s->host_features;
340d96e7
PB
92 break;
93 case SYBORG_VIRTIO_GUEST_FEATURES:
704a76fc 94 ret = vdev->guest_features;
340d96e7
PB
95 break;
96 case SYBORG_VIRTIO_QUEUE_BASE:
97 ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
98 break;
99 case SYBORG_VIRTIO_QUEUE_NUM:
100 ret = virtio_queue_get_num(vdev, vdev->queue_sel);
101 break;
102 case SYBORG_VIRTIO_QUEUE_SEL:
103 ret = vdev->queue_sel;
104 break;
105 case SYBORG_VIRTIO_STATUS:
106 ret = vdev->status;
107 break;
108 case SYBORG_VIRTIO_INT_ENABLE:
109 ret = s->int_enable;
110 break;
111 case SYBORG_VIRTIO_INT_STATUS:
112 ret = vdev->isr;
113 break;
114 default:
115 BADF("Bad read offset 0x%x\n", (int)offset);
116 return 0;
117 }
118 return ret;
119}
120
c227f099 121static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
340d96e7
PB
122 uint32_t value)
123{
124 SyborgVirtIOProxy *s = opaque;
125 VirtIODevice *vdev = s->vdev;
126
127 DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
128 if (offset >= SYBORG_VIRTIO_CONFIG) {
129 return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
130 value);
131 }
132 switch (offset >> 2) {
133 case SYBORG_VIRTIO_GUEST_FEATURES:
134 if (vdev->set_features)
135 vdev->set_features(vdev, value);
704a76fc 136 vdev->guest_features = value;
340d96e7
PB
137 break;
138 case SYBORG_VIRTIO_QUEUE_BASE:
7055e687
MT
139 if (value == 0)
140 virtio_reset(vdev);
141 else
142 virtio_queue_set_addr(vdev, vdev->queue_sel, value);
340d96e7
PB
143 break;
144 case SYBORG_VIRTIO_QUEUE_SEL:
145 if (value < VIRTIO_PCI_QUEUE_MAX)
146 vdev->queue_sel = value;
147 break;
148 case SYBORG_VIRTIO_QUEUE_NOTIFY:
7157e2e2
SH
149 if (value < VIRTIO_PCI_QUEUE_MAX) {
150 virtio_queue_notify(vdev, value);
151 }
340d96e7
PB
152 break;
153 case SYBORG_VIRTIO_STATUS:
3e607cb5 154 virtio_set_status(vdev, value & 0xFF);
340d96e7
PB
155 if (vdev->status == 0)
156 virtio_reset(vdev);
157 break;
158 case SYBORG_VIRTIO_INT_ENABLE:
159 s->int_enable = value;
160 virtio_update_irq(vdev);
161 break;
162 case SYBORG_VIRTIO_INT_STATUS:
163 vdev->isr &= ~value;
164 virtio_update_irq(vdev);
165 break;
166 default:
167 BADF("Bad write offset 0x%x\n", (int)offset);
168 break;
169 }
170}
171
c227f099 172static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
340d96e7
PB
173{
174 SyborgVirtIOProxy *s = opaque;
175 VirtIODevice *vdev = s->vdev;
176
177 DPRINTF("readw 0x%x\n", (int)offset);
178 if (offset >= SYBORG_VIRTIO_CONFIG) {
179 return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
180 }
181 BADF("Bad halfword read offset 0x%x\n", (int)offset);
182 return -1;
183}
184
c227f099 185static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
340d96e7
PB
186 uint32_t value)
187{
188 SyborgVirtIOProxy *s = opaque;
189 VirtIODevice *vdev = s->vdev;
190
191 DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
192 if (offset >= SYBORG_VIRTIO_CONFIG) {
193 return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
194 value);
195 }
196 BADF("Bad halfword write offset 0x%x\n", (int)offset);
197}
198
c227f099 199static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
340d96e7
PB
200{
201 SyborgVirtIOProxy *s = opaque;
202 VirtIODevice *vdev = s->vdev;
203
204 DPRINTF("readb 0x%x\n", (int)offset);
205 if (offset >= SYBORG_VIRTIO_CONFIG) {
206 return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
207 }
208 BADF("Bad byte read offset 0x%x\n", (int)offset);
209 return -1;
210}
211
c227f099 212static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
340d96e7
PB
213 uint32_t value)
214{
215 SyborgVirtIOProxy *s = opaque;
216 VirtIODevice *vdev = s->vdev;
217
218 DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
219 if (offset >= SYBORG_VIRTIO_CONFIG) {
220 return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
221 value);
222 }
223 BADF("Bad byte write offset 0x%x\n", (int)offset);
224}
225
d60efc6b 226static CPUReadMemoryFunc * const syborg_virtio_readfn[] = {
340d96e7
PB
227 syborg_virtio_readb,
228 syborg_virtio_readw,
229 syborg_virtio_readl
230};
231
d60efc6b 232static CPUWriteMemoryFunc * const syborg_virtio_writefn[] = {
340d96e7
PB
233 syborg_virtio_writeb,
234 syborg_virtio_writew,
235 syborg_virtio_writel
236};
237
7055e687 238static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
340d96e7
PB
239{
240 SyborgVirtIOProxy *proxy = opaque;
241 int level;
242
243 level = proxy->int_enable & proxy->vdev->isr;
244 DPRINTF("IRQ %d\n", level);
245 qemu_set_irq(proxy->irq, level != 0);
246}
247
6d74ca5a
MT
248static unsigned syborg_virtio_get_features(void *opaque)
249{
8172539d
MT
250 SyborgVirtIOProxy *proxy = opaque;
251 return proxy->host_features;
6d74ca5a
MT
252}
253
340d96e7 254static VirtIOBindings syborg_virtio_bindings = {
6d74ca5a
MT
255 .notify = syborg_virtio_update_irq,
256 .get_features = syborg_virtio_get_features,
340d96e7
PB
257};
258
81a322d4 259static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
340d96e7
PB
260{
261 int iomemtype;
262
263 proxy->vdev = vdev;
264
7055e687
MT
265 /* Don't support multiple vectors */
266 proxy->vdev->nvectors = 0;
340d96e7 267 sysbus_init_irq(&proxy->busdev, &proxy->irq);
1eed09cb 268 iomemtype = cpu_register_io_memory(syborg_virtio_readfn,
2507c12a
AG
269 syborg_virtio_writefn, proxy,
270 DEVICE_NATIVE_ENDIAN);
340d96e7
PB
271 sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
272
273 proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
274
a08d4367 275 qemu_register_reset(virtio_reset, vdev);
7055e687 276
340d96e7 277 virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
8172539d
MT
278 proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
279 proxy->host_features = vdev->get_features(vdev, proxy->host_features);
81a322d4 280 return 0;
340d96e7
PB
281}
282
283/* Device specific bindings. */
284
81a322d4 285static int syborg_virtio_net_init(SysBusDevice *dev)
340d96e7
PB
286{
287 VirtIODevice *vdev;
288 SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
289
f0c07c7c 290 vdev = virtio_net_init(&dev->qdev, &proxy->nic, &proxy->net);
81a322d4 291 return syborg_virtio_init(proxy, vdev);
340d96e7
PB
292}
293
97b15621
GH
294static SysBusDeviceInfo syborg_virtio_net_info = {
295 .init = syborg_virtio_net_init,
296 .qdev.name = "syborg,virtio-net",
297 .qdev.size = sizeof(SyborgVirtIOProxy),
298 .qdev.props = (Property[]) {
299 DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
8172539d 300 DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
f0c07c7c
AW
301 DEFINE_PROP_UINT32("x-txtimer", SyborgVirtIOProxy,
302 net.txtimer, TX_TIMER_INTERVAL),
e3f30488
AW
303 DEFINE_PROP_INT32("x-txburst", SyborgVirtIOProxy,
304 net.txburst, TX_BURST),
a697a334 305 DEFINE_PROP_STRING("tx", SyborgVirtIOProxy, net.tx),
97b15621
GH
306 DEFINE_PROP_END_OF_LIST(),
307 }
308};
309
340d96e7
PB
310static void syborg_virtio_register_devices(void)
311{
97b15621 312 sysbus_register_withprop(&syborg_virtio_net_info);
340d96e7
PB
313}
314
315device_init(syborg_virtio_register_devices)