Statistics
| Branch: | Revision:

root / hw / qdev.c @ 3320e56e

History | View | Annotate | Download (8.5 kB)

1
/*
2
 *  Dynamic device configuration and creation.
3
 *
4
 *  Copyright (c) 2009 CodeSourcery
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
/* The theory here is that it should be possible to create a machine without
21
   knowledge of specific devices.  Historically board init routines have
22
   passed a bunch of arguments to each device, requiring the board know
23
   exactly which device it is dealing with.  This file provides an abstract
24
   API for device configuration and initialization.  Devices will generally
25
   inherit from a particular bus (e.g. PCI or I2C) rather than
26
   this API directly.  */
27

    
28
#include "net.h"
29
#include "qdev.h"
30
#include "sysemu.h"
31
#include "monitor.h"
32

    
33
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
34
static BusState *main_system_bus;
35
extern struct BusInfo system_bus_info;
36

    
37
static DeviceInfo *device_info_list;
38

    
39
/* Register a new device type.  */
40
void qdev_register(DeviceInfo *info)
41
{
42
    assert(info->size >= sizeof(DeviceState));
43
    assert(!info->next);
44

    
45
    info->next = device_info_list;
46
    device_info_list = info;
47
}
48

    
49
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
50
{
51
    DeviceInfo *info;
52

    
53
    /* first check device names */
54
    for (info = device_info_list; info != NULL; info = info->next) {
55
        if (bus_info && info->bus_info != bus_info)
56
            continue;
57
        if (strcmp(info->name, name) != 0)
58
            continue;
59
        return info;
60
    }
61

    
62
    /* failing that check the aliases */
63
    for (info = device_info_list; info != NULL; info = info->next) {
64
        if (bus_info && info->bus_info != bus_info)
65
            continue;
66
        if (!info->alias)
67
            continue;
68
        if (strcmp(info->alias, name) != 0)
69
            continue;
70
        return info;
71
    }
72
    return NULL;
73
}
74

    
75
/* Create a new device.  This only initializes the device state structure
76
   and allows properties to be set.  qdev_init should be called to
77
   initialize the actual device emulation.  */
78
DeviceState *qdev_create(BusState *bus, const char *name)
79
{
80
    DeviceInfo *info;
81
    DeviceState *dev;
82

    
83
    if (!bus) {
84
        if (!main_system_bus) {
85
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
86
        }
87
        bus = main_system_bus;
88
    }
89

    
90
    info = qdev_find_info(bus->info, name);
91
    if (!info) {
92
        hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
93
    }
94

    
95
    dev = qemu_mallocz(info->size);
96
    dev->info = info;
97
    dev->parent_bus = bus;
98
    qdev_prop_set_defaults(dev, dev->info->props);
99
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
100
    qdev_prop_set_compat(dev);
101
    LIST_INSERT_HEAD(&bus->children, dev, sibling);
102
    return dev;
103
}
104

    
105
/* Initialize a device.  Device properties should be set before calling
106
   this function.  IRQs and MMIO regions should be connected/mapped after
107
   calling this function.  */
108
void qdev_init(DeviceState *dev)
109
{
110
    dev->info->init(dev, dev->info);
111
}
112

    
113
/* Unlink device from bus and free the structure.  */
114
void qdev_free(DeviceState *dev)
115
{
116
    LIST_REMOVE(dev, sibling);
117
    free(dev);
118
}
119

    
120
/* Get a character (serial) device interface.  */
121
CharDriverState *qdev_init_chardev(DeviceState *dev)
122
{
123
    static int next_serial;
124
    static int next_virtconsole;
125
    /* FIXME: This is a nasty hack that needs to go away.  */
126
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
127
        return virtcon_hds[next_virtconsole++];
128
    } else {
129
        return serial_hds[next_serial++];
130
    }
131
}
132

    
133
BusState *qdev_get_parent_bus(DeviceState *dev)
134
{
135
    return dev->parent_bus;
136
}
137

    
138
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
139
{
140
    assert(dev->num_gpio_in == 0);
141
    dev->num_gpio_in = n;
142
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
143
}
144

    
145
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
146
{
147
    assert(dev->num_gpio_out == 0);
148
    dev->num_gpio_out = n;
149
    dev->gpio_out = pins;
150
}
151

    
152
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
153
{
154
    assert(n >= 0 && n < dev->num_gpio_in);
155
    return dev->gpio_in[n];
156
}
157

    
158
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
159
{
160
    assert(n >= 0 && n < dev->num_gpio_out);
161
    dev->gpio_out[n] = pin;
162
}
163

    
164
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
165
                                      NetCanReceive *can_receive,
166
                                      NetReceive *receive,
167
                                      NetReceiveIOV *receive_iov,
168
                                      NetCleanup *cleanup,
169
                                      void *opaque)
170
{
171
    NICInfo *nd = dev->nd;
172
    assert(nd);
173
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
174
                                  receive, receive_iov, cleanup, opaque);
175
    return nd->vc;
176
}
177

    
178

    
179
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
180
{
181
    memcpy(macaddr, dev->nd->macaddr, 6);
182
}
183

    
184
static int next_block_unit[IF_COUNT];
185

    
186
/* Get a block device.  This should only be used for single-drive devices
187
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
188
   appropriate bus.  */
189
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
190
{
191
    int unit = next_block_unit[type]++;
192
    int index;
193

    
194
    index = drive_get_index(type, 0, unit);
195
    if (index == -1) {
196
        return NULL;
197
    }
198
    return drives_table[index].bdrv;
199
}
200

    
201
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
202
{
203
    BusState *bus;
204

    
205
    LIST_FOREACH(bus, &dev->child_bus, sibling) {
206
        if (strcmp(name, bus->name) == 0) {
207
            return bus;
208
        }
209
    }
210
    return NULL;
211
}
212

    
213
static int next_scsi_bus;
214

    
215
/* Create a scsi bus, and attach devices to it.  */
216
/* TODO: Actually create a scsi bus for hotplug to use.  */
217
void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
218
{
219
   int bus = next_scsi_bus++;
220
   int unit;
221
   int index;
222

    
223
   for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
224
       index = drive_get_index(IF_SCSI, bus, unit);
225
       if (index == -1) {
226
           continue;
227
       }
228
       attach(host, drives_table[index].bdrv, unit);
229
   }
230
}
231

    
232
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
233
{
234
    BusState *bus;
235

    
236
    bus = qemu_mallocz(info->size);
237
    bus->info = info;
238
    bus->parent = parent;
239
    bus->name = qemu_strdup(name);
240
    LIST_INIT(&bus->children);
241
    if (parent) {
242
        LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
243
    }
244
    return bus;
245
}
246

    
247
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
248
static void qbus_print(Monitor *mon, BusState *bus, int indent);
249

    
250
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
251
                             const char *prefix, int indent)
252
{
253
    char buf[64];
254

    
255
    if (!props)
256
        return;
257
    while (props->name) {
258
        if (props->info->print) {
259
            props->info->print(dev, props, buf, sizeof(buf));
260
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
261
        }
262
        props++;
263
    }
264
}
265

    
266
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
267
{
268
    BusState *child;
269
    qdev_printf("dev: %s\n", dev->info->name);
270
    indent += 2;
271
    if (dev->num_gpio_in) {
272
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
273
    }
274
    if (dev->num_gpio_out) {
275
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
276
    }
277
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
278
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
279
    if (dev->parent_bus->info->print_dev)
280
        dev->parent_bus->info->print_dev(mon, dev, indent);
281
    LIST_FOREACH(child, &dev->child_bus, sibling) {
282
        qbus_print(mon, child, indent);
283
    }
284
}
285

    
286
static void qbus_print(Monitor *mon, BusState *bus, int indent)
287
{
288
    struct DeviceState *dev;
289

    
290
    qdev_printf("bus: %s\n", bus->name);
291
    indent += 2;
292
    qdev_printf("type %s\n", bus->info->name);
293
    LIST_FOREACH(dev, &bus->children, sibling) {
294
        qdev_print(mon, dev, indent);
295
    }
296
}
297
#undef qdev_printf
298

    
299
void do_info_qtree(Monitor *mon)
300
{
301
    if (main_system_bus)
302
        qbus_print(mon, main_system_bus, 0);
303
}