Statistics
| Branch: | Revision:

root / hw / qdev.c @ 074f2fff

History | View | Annotate | Download (10.8 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, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20

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

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

    
34
struct DeviceProperty {
35
    const char *name;
36
    DevicePropType type;
37
    union {
38
        uint64_t i;
39
        void *ptr;
40
    } value;
41
    DeviceProperty *next;
42
};
43

    
44
struct DeviceType {
45
    DeviceInfo *info;
46
    DeviceType *next;
47
};
48

    
49
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
50
static BusState *main_system_bus;
51

    
52
static DeviceType *device_type_list;
53

    
54
/* Register a new device type.  */
55
void qdev_register(DeviceInfo *info)
56
{
57
    DeviceType *t;
58

    
59
    assert(info->size >= sizeof(DeviceState));
60

    
61
    t = qemu_mallocz(sizeof(DeviceType));
62
    t->next = device_type_list;
63
    device_type_list = t;
64
    t->info = info;
65
}
66

    
67
/* Create a new device.  This only initializes the device state structure
68
   and allows properties to be set.  qdev_init should be called to
69
   initialize the actual device emulation.  */
70
DeviceState *qdev_create(BusState *bus, const char *name)
71
{
72
    DeviceType *t;
73
    DeviceState *dev;
74

    
75
    for (t = device_type_list; t; t = t->next) {
76
        if (strcmp(t->info->name, name) == 0) {
77
            break;
78
        }
79
    }
80
    if (!t) {
81
        hw_error("Unknown device '%s'\n", name);
82
    }
83

    
84
    dev = qemu_mallocz(t->info->size);
85
    dev->type = t;
86

    
87
    if (!bus) {
88
        /* ???: This assumes system busses have no additional state.  */
89
        if (!main_system_bus) {
90
            main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
91
                                          NULL, "main-system-bus");
92
        }
93
        bus = main_system_bus;
94
    }
95
    if (t->info->bus_type != bus->type) {
96
        /* TODO: Print bus type names.  */
97
        hw_error("Device '%s' on wrong bus type (%d/%d)", name,
98
                 t->info->bus_type, bus->type);
99
    }
100
    dev->parent_bus = bus;
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->type->info->init(dev, dev->type->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
static DeviceProperty *create_prop(DeviceState *dev, const char *name,
121
                                   DevicePropType type)
122
{
123
    DeviceProperty *prop;
124

    
125
    /* TODO: Check for duplicate properties.  */
126
    prop = qemu_mallocz(sizeof(*prop));
127
    prop->name = qemu_strdup(name);
128
    prop->type = type;
129
    prop->next = dev->props;
130
    dev->props = prop;
131

    
132
    return prop;
133
}
134

    
135
void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
136
{
137
    DeviceProperty *prop;
138

    
139
    prop = create_prop(dev, name, PROP_TYPE_INT);
140
    prop->value.i = value;
141
}
142

    
143
void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
144
{
145
    DeviceProperty *prop;
146

    
147
    prop = create_prop(dev, name, PROP_TYPE_DEV);
148
    prop->value.ptr = value;
149
}
150

    
151
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
152
{
153
    DeviceProperty *prop;
154

    
155
    prop = create_prop(dev, name, PROP_TYPE_PTR);
156
    prop->value.ptr = value;
157
}
158

    
159
void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
160
{
161
    assert(!dev->nd);
162
    dev->nd = nd;
163
}
164

    
165

    
166
/* Get a character (serial) device interface.  */
167
CharDriverState *qdev_init_chardev(DeviceState *dev)
168
{
169
    static int next_serial;
170
    static int next_virtconsole;
171
    /* FIXME: This is a nasty hack that needs to go away.  */
172
    if (strncmp(dev->type->info->name, "virtio", 6) == 0) {
173
        return virtcon_hds[next_virtconsole++];
174
    } else {
175
        return serial_hds[next_serial++];
176
    }
177
}
178

    
179
BusState *qdev_get_parent_bus(DeviceState *dev)
180
{
181
    return dev->parent_bus;
182
}
183

    
184
static DeviceProperty *find_prop(DeviceState *dev, const char *name,
185
                                 DevicePropType type)
186
{
187
    DeviceProperty *prop;
188

    
189
    for (prop = dev->props; prop; prop = prop->next) {
190
        if (strcmp(prop->name, name) == 0) {
191
            assert (prop->type == type);
192
            return prop;
193
        }
194
    }
195
    return NULL;
196
}
197

    
198
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
199
{
200
    DeviceProperty *prop;
201

    
202
    prop = find_prop(dev, name, PROP_TYPE_INT);
203
    if (!prop) {
204
        return def;
205
    }
206

    
207
    return prop->value.i;
208
}
209

    
210
void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
211
{
212
    DeviceProperty *prop;
213

    
214
    prop = find_prop(dev, name, PROP_TYPE_PTR);
215
    assert(prop);
216
    return prop->value.ptr;
217
}
218

    
219
DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
220
{
221
    DeviceProperty *prop;
222

    
223
    prop = find_prop(dev, name, PROP_TYPE_DEV);
224
    if (!prop) {
225
        return NULL;
226
    }
227
    return prop->value.ptr;
228
}
229

    
230
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
231
{
232
    assert(dev->num_gpio_in == 0);
233
    dev->num_gpio_in = n;
234
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
235
}
236

    
237
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
238
{
239
    assert(dev->num_gpio_out == 0);
240
    dev->num_gpio_out = n;
241
    dev->gpio_out = pins;
242
}
243

    
244
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
245
{
246
    assert(n >= 0 && n < dev->num_gpio_in);
247
    return dev->gpio_in[n];
248
}
249

    
250
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
251
{
252
    assert(n >= 0 && n < dev->num_gpio_out);
253
    dev->gpio_out[n] = pin;
254
}
255

    
256
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
257
                                      NetCanReceive *can_receive,
258
                                      NetReceive *receive,
259
                                      NetReceiveIOV *receive_iov,
260
                                      NetCleanup *cleanup,
261
                                      void *opaque)
262
{
263
    NICInfo *nd = dev->nd;
264
    assert(nd);
265
    return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
266
                                receive, receive_iov, cleanup, opaque);
267
}
268

    
269

    
270
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
271
{
272
    memcpy(macaddr, dev->nd->macaddr, 6);
273
}
274

    
275
static int next_block_unit[IF_COUNT];
276

    
277
/* Get a block device.  This should only be used for single-drive devices
278
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
279
   appropriate bus.  */
280
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
281
{
282
    int unit = next_block_unit[type]++;
283
    int index;
284

    
285
    index = drive_get_index(type, 0, unit);
286
    if (index == -1) {
287
        return NULL;
288
    }
289
    return drives_table[index].bdrv;
290
}
291

    
292
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
293
{
294
    BusState *bus;
295

    
296
    LIST_FOREACH(bus, &dev->child_bus, sibling) {
297
        if (strcmp(name, bus->name) == 0) {
298
            return bus;
299
        }
300
    }
301
    return NULL;
302
}
303

    
304
static int next_scsi_bus;
305

    
306
/* Create a scsi bus, and attach devices to it.  */
307
/* TODO: Actually create a scsi bus for hotplug to use.  */
308
void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
309
{
310
   int bus = next_scsi_bus++;
311
   int unit;
312
   int index;
313

    
314
   for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
315
       index = drive_get_index(IF_SCSI, bus, unit);
316
       if (index == -1) {
317
           continue;
318
       }
319
       attach(host, drives_table[index].bdrv, unit);
320
   }
321
}
322

    
323
BusState *qbus_create(BusType type, size_t size,
324
                      DeviceState *parent, const char *name)
325
{
326
    BusState *bus;
327

    
328
    bus = qemu_mallocz(size);
329
    bus->type = type;
330
    bus->parent = parent;
331
    bus->name = qemu_strdup(name);
332
    LIST_INIT(&bus->children);
333
    if (parent) {
334
        LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
335
    }
336
    return bus;
337
}
338

    
339
static const char *bus_type_names[] = {
340
    [ BUS_TYPE_SYSTEM ] = "System",
341
    [ BUS_TYPE_PCI ]    = "PCI",
342
    [ BUS_TYPE_SCSI ]   = "SCSI",
343
    [ BUS_TYPE_I2C ]    = "I2C",
344
    [ BUS_TYPE_SSI ]    = "SSI",
345
};
346

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

    
350
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
351
{
352
    DeviceProperty *prop;
353
    BusState *child;
354
    qdev_printf("dev: %s\n", dev->type->info->name);
355
    indent += 2;
356
    if (dev->num_gpio_in) {
357
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
358
    }
359
    if (dev->num_gpio_out) {
360
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
361
    }
362
    for (prop = dev->props; prop; prop = prop->next) {
363
        switch (prop->type) {
364
        case PROP_TYPE_INT:
365
            qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
366
                        prop->value.i);
367
            break;
368
        case PROP_TYPE_PTR:
369
            qdev_printf("prop-ptr %s\n", prop->name);
370
            break;
371
        case PROP_TYPE_DEV:
372
            qdev_printf("prop-dev %s %s\n", prop->name,
373
                        ((DeviceState *)prop->value.ptr)->type->info->name);
374
            break;
375
        default:
376
            qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
377
            break;
378
        }
379
    }
380
    switch (dev->parent_bus->type) {
381
    case BUS_TYPE_SYSTEM:
382
        sysbus_dev_print(mon, dev, indent);
383
        break;
384
    default:
385
        break;
386
    }
387
    LIST_FOREACH(child, &dev->child_bus, sibling) {
388
        qbus_print(mon, child, indent);
389
    }
390
}
391

    
392
static void qbus_print(Monitor *mon, BusState *bus, int indent)
393
{
394
    struct DeviceState *dev;
395

    
396
    qdev_printf("bus: %s\n", bus->name);
397
    indent += 2;
398
    qdev_printf("type %s\n", bus_type_names[bus->type]);
399
    LIST_FOREACH(dev, &bus->children, sibling) {
400
        qdev_print(mon, dev, indent);
401
    }
402
}
403
#undef qdev_printf
404

    
405
void do_info_qtree(Monitor *mon)
406
{
407
    if (main_system_bus)
408
        qbus_print(mon, main_system_bus, 0);
409
}