Revision 340d96e7

b/Makefile.target
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)
b/hw/syborg.c
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 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;
b/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
        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)

Also available in: Unified diff