Fix OpenSolaris build breaking typos
[qemu] / hw / syborg_virtio.c
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         if (value == 0)
138             virtio_reset(vdev);
139         else
140             virtio_queue_set_addr(vdev, vdev->queue_sel, value);
141         break;
142     case SYBORG_VIRTIO_QUEUE_SEL:
143         if (value < VIRTIO_PCI_QUEUE_MAX)
144             vdev->queue_sel = value;
145         break;
146     case SYBORG_VIRTIO_QUEUE_NOTIFY:
147         virtio_queue_notify(vdev, value);
148         break;
149     case SYBORG_VIRTIO_STATUS:
150         vdev->status = value & 0xFF;
151         if (vdev->status == 0)
152             virtio_reset(vdev);
153         break;
154     case SYBORG_VIRTIO_INT_ENABLE:
155         s->int_enable = value;
156         virtio_update_irq(vdev);
157         break;
158     case SYBORG_VIRTIO_INT_STATUS:
159         vdev->isr &= ~value;
160         virtio_update_irq(vdev);
161         break;
162     default:
163         BADF("Bad write offset 0x%x\n", (int)offset);
164         break;
165     }
166 }
167
168 static uint32_t syborg_virtio_readw(void *opaque, target_phys_addr_t offset)
169 {
170     SyborgVirtIOProxy *s = opaque;
171     VirtIODevice *vdev = s->vdev;
172
173     DPRINTF("readw 0x%x\n", (int)offset);
174     if (offset >= SYBORG_VIRTIO_CONFIG) {
175         return virtio_config_readw(vdev, offset - SYBORG_VIRTIO_CONFIG);
176     }
177     BADF("Bad halfword read offset 0x%x\n", (int)offset);
178     return -1;
179 }
180
181 static void syborg_virtio_writew(void *opaque, target_phys_addr_t offset,
182                                  uint32_t value)
183 {
184     SyborgVirtIOProxy *s = opaque;
185     VirtIODevice *vdev = s->vdev;
186
187     DPRINTF("writew 0x%x = 0x%x\n", (int)offset, value);
188     if (offset >= SYBORG_VIRTIO_CONFIG) {
189         return virtio_config_writew(vdev, offset - SYBORG_VIRTIO_CONFIG,
190                                     value);
191     }
192     BADF("Bad halfword write offset 0x%x\n", (int)offset);
193 }
194
195 static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
196 {
197     SyborgVirtIOProxy *s = opaque;
198     VirtIODevice *vdev = s->vdev;
199
200     DPRINTF("readb 0x%x\n", (int)offset);
201     if (offset >= SYBORG_VIRTIO_CONFIG) {
202         return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
203     }
204     BADF("Bad byte read offset 0x%x\n", (int)offset);
205     return -1;
206 }
207
208 static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
209                                  uint32_t value)
210 {
211     SyborgVirtIOProxy *s = opaque;
212     VirtIODevice *vdev = s->vdev;
213
214     DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
215     if (offset >= SYBORG_VIRTIO_CONFIG) {
216         return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
217                                     value);
218     }
219     BADF("Bad byte write offset 0x%x\n", (int)offset);
220 }
221
222 static CPUReadMemoryFunc * const syborg_virtio_readfn[] = {
223      syborg_virtio_readb,
224      syborg_virtio_readw,
225      syborg_virtio_readl
226 };
227
228 static CPUWriteMemoryFunc * const syborg_virtio_writefn[] = {
229      syborg_virtio_writeb,
230      syborg_virtio_writew,
231      syborg_virtio_writel
232 };
233
234 static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
235 {
236     SyborgVirtIOProxy *proxy = opaque;
237     int level;
238
239     level = proxy->int_enable & proxy->vdev->isr;
240     DPRINTF("IRQ %d\n", level);
241     qemu_set_irq(proxy->irq, level != 0);
242 }
243
244 static VirtIOBindings syborg_virtio_bindings = {
245     .notify = syborg_virtio_update_irq
246 };
247
248 static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
249 {
250     int iomemtype;
251
252     proxy->vdev = vdev;
253
254     /* Don't support multiple vectors */
255     proxy->vdev->nvectors = 0;
256     sysbus_init_irq(&proxy->busdev, &proxy->irq);
257     iomemtype = cpu_register_io_memory(syborg_virtio_readfn,
258                                        syborg_virtio_writefn, proxy);
259     sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
260
261     proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
262
263     qemu_register_reset(virtio_reset, vdev);
264
265     virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
266     return 0;
267 }
268
269 /* Device specific bindings.  */
270
271 static int syborg_virtio_net_init(SysBusDevice *dev)
272 {
273     VirtIODevice *vdev;
274     SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
275
276     vdev = virtio_net_init(&dev->qdev);
277     return syborg_virtio_init(proxy, vdev);
278 }
279
280 static void syborg_virtio_register_devices(void)
281 {
282     sysbus_register_dev("syborg,virtio-net", sizeof(SyborgVirtIOProxy),
283                         syborg_virtio_net_init);
284 }
285
286 device_init(syborg_virtio_register_devices)