Statistics
| Branch: | Revision:

root / hw / qdev.c @ 72cf2d4f

History | View | Annotate | Download (16.9 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

    
36
static DeviceInfo *device_info_list;
37

    
38
static BusState *qbus_find_recursive(BusState *bus, const char *name,
39
                                     const BusInfo *info);
40
static BusState *qbus_find(const char *path);
41

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

    
48
    info->next = device_info_list;
49
    device_info_list = info;
50
}
51

    
52
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
53
{
54
    DeviceInfo *info;
55

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

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

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

    
86
    if (!bus) {
87
        if (!main_system_bus) {
88
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
89
        }
90
        bus = main_system_bus;
91
    }
92

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

    
98
    dev = qemu_mallocz(info->size);
99
    dev->info = info;
100
    dev->parent_bus = bus;
101
    qdev_prop_set_defaults(dev, dev->info->props);
102
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
103
    qdev_prop_set_compat(dev);
104
    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
105
    return dev;
106
}
107

    
108
static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
109
{
110
    int pos = 0;
111
    int ret;
112

    
113
    ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
114
                   info->name, info->bus_info->name);
115
    pos += MIN(len-pos,ret);
116
    if (info->alias) {
117
        ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
118
        pos += MIN(len-pos,ret);
119
    }
120
    if (info->desc) {
121
        ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
122
        pos += MIN(len-pos,ret);
123
    }
124
    if (info->no_user) {
125
        ret = snprintf(dest+pos, len-pos, ", no-user");
126
        pos += MIN(len-pos,ret);
127
    }
128
    return pos;
129
}
130

    
131
static int set_property(const char *name, const char *value, void *opaque)
132
{
133
    DeviceState *dev = opaque;
134

    
135
    if (strcmp(name, "driver") == 0)
136
        return 0;
137
    if (strcmp(name, "bus") == 0)
138
        return 0;
139

    
140
    if (-1 == qdev_prop_parse(dev, name, value)) {
141
        qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
142
                   name, value, dev->info->name);
143
        return -1;
144
    }
145
    return 0;
146
}
147

    
148
DeviceState *qdev_device_add(QemuOpts *opts)
149
{
150
    const char *driver, *path, *id;
151
    DeviceInfo *info;
152
    DeviceState *qdev;
153
    BusState *bus;
154

    
155
    driver = qemu_opt_get(opts, "driver");
156
    if (!driver) {
157
        qemu_error("-device: no driver specified\n");
158
        return NULL;
159
    }
160
    if (strcmp(driver, "?") == 0) {
161
        char msg[256];
162
        for (info = device_info_list; info != NULL; info = info->next) {
163
            qdev_print_devinfo(info, msg, sizeof(msg));
164
            qemu_error("%s\n", msg);
165
        }
166
        return NULL;
167
    }
168

    
169
    /* find driver */
170
    info = qdev_find_info(NULL, driver);
171
    if (!info) {
172
        qemu_error("Device \"%s\" not found.  Try -device '?' for a list.\n",
173
                   driver);
174
        return NULL;
175
    }
176
    if (info->no_user) {
177
        qemu_error("device \"%s\" can't be added via command line\n",
178
                   info->name);
179
        return NULL;
180
    }
181

    
182
    /* find bus */
183
    path = qemu_opt_get(opts, "bus");
184
    if (path != NULL) {
185
        bus = qbus_find(path);
186
    } else {
187
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
188
    }
189
    if (!bus) {
190
        qemu_error("Did not find %s bus for %s\n",
191
                   path ? path : info->bus_info->name, info->name);
192
        return NULL;
193
    }
194

    
195
    /* create device, set properties */
196
    qdev = qdev_create(bus, driver);
197
    id = qemu_opts_id(opts);
198
    if (id) {
199
        qdev->id = id;
200
    }
201
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
202
        qdev_free(qdev);
203
        return NULL;
204
    }
205
    if (qdev_init(qdev) != 0) {
206
        qdev_free(qdev);
207
        return NULL;
208
    }
209
    return qdev;
210
}
211

    
212
/* Initialize a device.  Device properties should be set before calling
213
   this function.  IRQs and MMIO regions should be connected/mapped after
214
   calling this function.  */
215
int qdev_init(DeviceState *dev)
216
{
217
    int rc;
218

    
219
    rc = dev->info->init(dev, dev->info);
220
    if (rc < 0)
221
        return rc;
222
    if (dev->info->reset)
223
        qemu_register_reset(dev->info->reset, dev);
224
    if (dev->info->vmsd)
225
        vmstate_register(-1, dev->info->vmsd, dev);
226
    return 0;
227
}
228

    
229
/* Unlink device from bus and free the structure.  */
230
void qdev_free(DeviceState *dev)
231
{
232
#if 0 /* FIXME: need sane vmstate_unregister function */
233
    if (dev->info->vmsd)
234
        vmstate_unregister(dev->info->vmsd, dev);
235
#endif
236
    if (dev->info->reset)
237
        qemu_unregister_reset(dev->info->reset, dev);
238
    QLIST_REMOVE(dev, sibling);
239
    qemu_free(dev);
240
}
241

    
242
/* Get a character (serial) device interface.  */
243
CharDriverState *qdev_init_chardev(DeviceState *dev)
244
{
245
    static int next_serial;
246
    static int next_virtconsole;
247
    /* FIXME: This is a nasty hack that needs to go away.  */
248
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
249
        return virtcon_hds[next_virtconsole++];
250
    } else {
251
        return serial_hds[next_serial++];
252
    }
253
}
254

    
255
BusState *qdev_get_parent_bus(DeviceState *dev)
256
{
257
    return dev->parent_bus;
258
}
259

    
260
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
261
{
262
    assert(dev->num_gpio_in == 0);
263
    dev->num_gpio_in = n;
264
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
265
}
266

    
267
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
268
{
269
    assert(dev->num_gpio_out == 0);
270
    dev->num_gpio_out = n;
271
    dev->gpio_out = pins;
272
}
273

    
274
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
275
{
276
    assert(n >= 0 && n < dev->num_gpio_in);
277
    return dev->gpio_in[n];
278
}
279

    
280
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
281
{
282
    assert(n >= 0 && n < dev->num_gpio_out);
283
    dev->gpio_out[n] = pin;
284
}
285

    
286
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
287
                                      NetCanReceive *can_receive,
288
                                      NetReceive *receive,
289
                                      NetReceiveIOV *receive_iov,
290
                                      NetCleanup *cleanup,
291
                                      void *opaque)
292
{
293
    NICInfo *nd = dev->nd;
294
    assert(nd);
295
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
296
                                  receive, receive_iov, cleanup, opaque);
297
    return nd->vc;
298
}
299

    
300

    
301
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
302
{
303
    memcpy(macaddr, dev->nd->macaddr, 6);
304
}
305

    
306
static int next_block_unit[IF_COUNT];
307

    
308
/* Get a block device.  This should only be used for single-drive devices
309
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
310
   appropriate bus.  */
311
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
312
{
313
    int unit = next_block_unit[type]++;
314
    DriveInfo *dinfo;
315

    
316
    dinfo = drive_get(type, 0, unit);
317
    return dinfo ? dinfo->bdrv : NULL;
318
}
319

    
320
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
321
{
322
    BusState *bus;
323

    
324
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
325
        if (strcmp(name, bus->name) == 0) {
326
            return bus;
327
        }
328
    }
329
    return NULL;
330
}
331

    
332
static BusState *qbus_find_recursive(BusState *bus, const char *name,
333
                                     const BusInfo *info)
334
{
335
    DeviceState *dev;
336
    BusState *child, *ret;
337
    int match = 1;
338

    
339
    if (name && (strcmp(bus->name, name) != 0)) {
340
        match = 0;
341
    }
342
    if (info && (bus->info != info)) {
343
        match = 0;
344
    }
345
    if (match) {
346
        return bus;
347
    }
348

    
349
    QLIST_FOREACH(dev, &bus->children, sibling) {
350
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
351
            ret = qbus_find_recursive(child, name, info);
352
            if (ret) {
353
                return ret;
354
            }
355
        }
356
    }
357
    return NULL;
358
}
359

    
360
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
361
{
362
    BusState *child;
363
    const char *sep = " ";
364
    int pos = 0;
365

    
366
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
367
                    dev->id ? dev->id : dev->info->name);
368
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
369
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
370
        sep = ", ";
371
    }
372
}
373

    
374
static void qbus_list_dev(BusState *bus, char *dest, int len)
375
{
376
    DeviceState *dev;
377
    const char *sep = " ";
378
    int pos = 0;
379

    
380
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
381
                    bus->name);
382
    QLIST_FOREACH(dev, &bus->children, sibling) {
383
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
384
                        sep, dev->info->name);
385
        if (dev->id)
386
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
387
        sep = ", ";
388
    }
389
}
390

    
391
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
392
{
393
    BusState *child;
394

    
395
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
396
        if (strcmp(child->name, elem) == 0) {
397
            return child;
398
        }
399
    }
400
    return NULL;
401
}
402

    
403
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
404
{
405
    DeviceState *dev;
406

    
407
    /*
408
     * try to match in order:
409
     *   (1) instance id, if present
410
     *   (2) driver name
411
     *   (3) driver alias, if present
412
     */
413
    QLIST_FOREACH(dev, &bus->children, sibling) {
414
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
415
            return dev;
416
        }
417
    }
418
    QLIST_FOREACH(dev, &bus->children, sibling) {
419
        if (strcmp(dev->info->name, elem) == 0) {
420
            return dev;
421
        }
422
    }
423
    QLIST_FOREACH(dev, &bus->children, sibling) {
424
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
425
            return dev;
426
        }
427
    }
428
    return NULL;
429
}
430

    
431
static BusState *qbus_find(const char *path)
432
{
433
    DeviceState *dev;
434
    BusState *bus;
435
    char elem[128], msg[256];
436
    int pos, len;
437

    
438
    /* find start element */
439
    if (path[0] == '/') {
440
        bus = main_system_bus;
441
        pos = 0;
442
    } else {
443
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
444
            qemu_error("path parse error (\"%s\")\n", path);
445
            return NULL;
446
        }
447
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
448
        if (!bus) {
449
            qemu_error("bus \"%s\" not found\n", elem);
450
            return NULL;
451
        }
452
        pos = len;
453
    }
454

    
455
    for (;;) {
456
        if (path[pos] == '\0') {
457
            /* we are done */
458
            return bus;
459
        }
460

    
461
        /* find device */
462
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
463
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
464
            return NULL;
465
        }
466
        pos += len;
467
        dev = qbus_find_dev(bus, elem);
468
        if (!dev) {
469
            qbus_list_dev(bus, msg, sizeof(msg));
470
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
471
            return NULL;
472
        }
473
        if (path[pos] == '\0') {
474
            /* last specified element is a device.  If it has exactly
475
             * one child bus accept it nevertheless */
476
            switch (dev->num_child_bus) {
477
            case 0:
478
                qemu_error("device has no child bus (%s)\n", path);
479
                return NULL;
480
            case 1:
481
                return QLIST_FIRST(&dev->child_bus);
482
            default:
483
                qbus_list_bus(dev, msg, sizeof(msg));
484
                qemu_error("device has multiple child busses (%s)\n%s\n",
485
                           path, msg);
486
                return NULL;
487
            }
488
        }
489

    
490
        /* find bus */
491
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
492
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
493
            return NULL;
494
        }
495
        pos += len;
496
        bus = qbus_find_bus(dev, elem);
497
        if (!bus) {
498
            qbus_list_bus(dev, msg, sizeof(msg));
499
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
500
            return NULL;
501
        }
502
    }
503
}
504

    
505
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
506
{
507
    BusState *bus;
508
    char *buf;
509
    int i,len;
510

    
511
    bus = qemu_mallocz(info->size);
512
    bus->info = info;
513
    bus->parent = parent;
514

    
515
    if (name) {
516
        /* use supplied name */
517
        bus->name = qemu_strdup(name);
518
    } else if (parent && parent->id) {
519
        /* parent device has id -> use it for bus name */
520
        len = strlen(parent->id) + 16;
521
        buf = qemu_malloc(len);
522
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
523
        bus->name = buf;
524
    } else {
525
        /* no id -> use lowercase bus type for bus name */
526
        len = strlen(info->name) + 16;
527
        buf = qemu_malloc(len);
528
        len = snprintf(buf, len, "%s.%d", info->name,
529
                       parent ? parent->num_child_bus : 0);
530
        for (i = 0; i < len; i++)
531
            buf[i] = qemu_tolower(buf[i]);
532
        bus->name = buf;
533
    }
534

    
535
    QLIST_INIT(&bus->children);
536
    if (parent) {
537
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
538
        parent->num_child_bus++;
539
    }
540
    return bus;
541
}
542

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

    
546
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
547
                             const char *prefix, int indent)
548
{
549
    char buf[64];
550

    
551
    if (!props)
552
        return;
553
    while (props->name) {
554
        if (props->info->print) {
555
            props->info->print(dev, props, buf, sizeof(buf));
556
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
557
        }
558
        props++;
559
    }
560
}
561

    
562
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
563
{
564
    BusState *child;
565
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
566
                dev->id ? dev->id : "");
567
    indent += 2;
568
    if (dev->num_gpio_in) {
569
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
570
    }
571
    if (dev->num_gpio_out) {
572
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
573
    }
574
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
575
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
576
    if (dev->parent_bus->info->print_dev)
577
        dev->parent_bus->info->print_dev(mon, dev, indent);
578
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
579
        qbus_print(mon, child, indent);
580
    }
581
}
582

    
583
static void qbus_print(Monitor *mon, BusState *bus, int indent)
584
{
585
    struct DeviceState *dev;
586

    
587
    qdev_printf("bus: %s\n", bus->name);
588
    indent += 2;
589
    qdev_printf("type %s\n", bus->info->name);
590
    QLIST_FOREACH(dev, &bus->children, sibling) {
591
        qdev_print(mon, dev, indent);
592
    }
593
}
594
#undef qdev_printf
595

    
596
void do_info_qtree(Monitor *mon)
597
{
598
    if (main_system_bus)
599
        qbus_print(mon, main_system_bus, 0);
600
}
601

    
602
void do_info_qdm(Monitor *mon)
603
{
604
    DeviceInfo *info;
605
    char msg[256];
606

    
607
    for (info = device_info_list; info != NULL; info = info->next) {
608
        qdev_print_devinfo(info, msg, sizeof(msg));
609
        monitor_printf(mon, "%s\n", msg);
610
    }
611
}