Statistics
| Branch: | Revision:

root / hw / qdev.c @ c64eafaf

History | View | Annotate | Download (20.3 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
#include "qerror.h"
33

    
34
static int qdev_hotplug = 0;
35

    
36
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
37
static BusState *main_system_bus;
38

    
39
DeviceInfo *device_info_list;
40

    
41
static BusState *qbus_find_recursive(BusState *bus, const char *name,
42
                                     const BusInfo *info);
43
static BusState *qbus_find(const char *path);
44

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

    
51
    info->next = device_info_list;
52
    device_info_list = info;
53
}
54

    
55
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
56
{
57
    DeviceInfo *info;
58

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

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

    
81
static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
82
{
83
    DeviceState *dev;
84

    
85
    assert(bus->info == info->bus_info);
86
    dev = qemu_mallocz(info->size);
87
    dev->info = info;
88
    dev->parent_bus = bus;
89
    qdev_prop_set_defaults(dev, dev->info->props);
90
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
91
    qdev_prop_set_globals(dev);
92
    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
93
    if (qdev_hotplug) {
94
        assert(bus->allow_hotplug);
95
        dev->hotplugged = 1;
96
    }
97
    dev->state = DEV_STATE_CREATED;
98
    return dev;
99
}
100

    
101
/* Create a new device.  This only initializes the device state structure
102
   and allows properties to be set.  qdev_init should be called to
103
   initialize the actual device emulation.  */
104
DeviceState *qdev_create(BusState *bus, const char *name)
105
{
106
    DeviceInfo *info;
107

    
108
    if (!bus) {
109
        if (!main_system_bus) {
110
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
111
        }
112
        bus = main_system_bus;
113
    }
114

    
115
    info = qdev_find_info(bus->info, name);
116
    if (!info) {
117
        hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
118
    }
119

    
120
    return qdev_create_from_info(bus, info);
121
}
122

    
123
static void qdev_print_devinfo(DeviceInfo *info)
124
{
125
    error_printf("name \"%s\", bus %s",
126
                 info->name, info->bus_info->name);
127
    if (info->alias) {
128
        error_printf(", alias \"%s\"", info->alias);
129
    }
130
    if (info->desc) {
131
        error_printf(", desc \"%s\"", info->desc);
132
    }
133
    if (info->no_user) {
134
        error_printf(", no-user");
135
    }
136
    error_printf("\n");
137
}
138

    
139
static int set_property(const char *name, const char *value, void *opaque)
140
{
141
    DeviceState *dev = opaque;
142

    
143
    if (strcmp(name, "driver") == 0)
144
        return 0;
145
    if (strcmp(name, "bus") == 0)
146
        return 0;
147

    
148
    if (qdev_prop_parse(dev, name, value) == -1) {
149
        error_report("can't set property \"%s\" to \"%s\" for \"%s\"",
150
                     name, value, dev->info->name);
151
        return -1;
152
    }
153
    return 0;
154
}
155

    
156
int qdev_device_help(QemuOpts *opts)
157
{
158
    const char *driver;
159
    DeviceInfo *info;
160
    Property *prop;
161

    
162
    driver = qemu_opt_get(opts, "driver");
163
    if (driver && !strcmp(driver, "?")) {
164
        for (info = device_info_list; info != NULL; info = info->next) {
165
            if (info->no_user) {
166
                continue;       /* not available, don't show */
167
            }
168
            qdev_print_devinfo(info);
169
        }
170
        return 1;
171
    }
172

    
173
    if (!qemu_opt_get(opts, "?")) {
174
        return 0;
175
    }
176

    
177
    info = qdev_find_info(NULL, driver);
178
    if (!info) {
179
        return 0;
180
    }
181

    
182
    for (prop = info->props; prop && prop->name; prop++) {
183
        error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
184
    }
185
    return 1;
186
}
187

    
188
DeviceState *qdev_device_add(QemuOpts *opts)
189
{
190
    const char *driver, *path, *id;
191
    DeviceInfo *info;
192
    DeviceState *qdev;
193
    BusState *bus;
194

    
195
    driver = qemu_opt_get(opts, "driver");
196
    if (!driver) {
197
        error_report("-device: no driver specified");
198
        return NULL;
199
    }
200

    
201
    /* find driver */
202
    info = qdev_find_info(NULL, driver);
203
    if (!info || info->no_user) {
204
        qerror_report(QERR_DEVICE_NOT_FOUND, driver);
205
        return NULL;
206
    }
207

    
208
    /* find bus */
209
    path = qemu_opt_get(opts, "bus");
210
    if (path != NULL) {
211
        bus = qbus_find(path);
212
        if (bus && bus->info != info->bus_info) {
213
            error_report("Device '%s' can't go on a %s bus",
214
                         driver, bus->info->name);
215
            return NULL;
216
        }
217
    } else {
218
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
219
    }
220
    if (!bus) {
221
        error_report("Did not find %s bus for %s",
222
                     path ? path : info->bus_info->name, info->name);
223
        return NULL;
224
    }
225
    if (qdev_hotplug && !bus->allow_hotplug) {
226
        error_report("Bus %s does not support hotplugging",
227
                     bus->name);
228
        return NULL;
229
    }
230

    
231
    /* create device, set properties */
232
    qdev = qdev_create_from_info(bus, info);
233
    id = qemu_opts_id(opts);
234
    if (id) {
235
        qdev->id = id;
236
    }
237
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
238
        qdev_free(qdev);
239
        return NULL;
240
    }
241
    if (qdev_init(qdev) < 0) {
242
        error_report("Error initializing device %s", driver);
243
        return NULL;
244
    }
245
    qdev->opts = opts;
246
    return qdev;
247
}
248

    
249
static void qdev_reset(void *opaque)
250
{
251
    DeviceState *dev = opaque;
252
    if (dev->info->reset)
253
        dev->info->reset(dev);
254
}
255

    
256
/* Initialize a device.  Device properties should be set before calling
257
   this function.  IRQs and MMIO regions should be connected/mapped after
258
   calling this function.
259
   On failure, destroy the device and return negative value.
260
   Return 0 on success.  */
261
int qdev_init(DeviceState *dev)
262
{
263
    int rc;
264

    
265
    assert(dev->state == DEV_STATE_CREATED);
266
    rc = dev->info->init(dev, dev->info);
267
    if (rc < 0) {
268
        qdev_free(dev);
269
        return rc;
270
    }
271
    qemu_register_reset(qdev_reset, dev);
272
    if (dev->info->vmsd)
273
        vmstate_register(-1, dev->info->vmsd, dev);
274
    dev->state = DEV_STATE_INITIALIZED;
275
    return 0;
276
}
277

    
278
int qdev_unplug(DeviceState *dev)
279
{
280
    if (!dev->parent_bus->allow_hotplug) {
281
        error_report("Bus %s does not support hotplugging",
282
                     dev->parent_bus->name);
283
        return -1;
284
    }
285
    assert(dev->info->unplug != NULL);
286

    
287
    return dev->info->unplug(dev);
288
}
289

    
290
/* can be used as ->unplug() callback for the simple cases */
291
int qdev_simple_unplug_cb(DeviceState *dev)
292
{
293
    /* just zap it */
294
    qdev_free(dev);
295
    return 0;
296
}
297

    
298
/* Like qdev_init(), but terminate program via hw_error() instead of
299
   returning an error value.  This is okay during machine creation.
300
   Don't use for hotplug, because there callers need to recover from
301
   failure.  Exception: if you know the device's init() callback can't
302
   fail, then qdev_init_nofail() can't fail either, and is therefore
303
   usable even then.  But relying on the device implementation that
304
   way is somewhat unclean, and best avoided.  */
305
void qdev_init_nofail(DeviceState *dev)
306
{
307
    DeviceInfo *info = dev->info;
308

    
309
    if (qdev_init(dev) < 0)
310
        hw_error("Initialization of device %s failed\n", info->name);
311
}
312

    
313
/* Unlink device from bus and free the structure.  */
314
void qdev_free(DeviceState *dev)
315
{
316
    BusState *bus;
317

    
318
    if (dev->state == DEV_STATE_INITIALIZED) {
319
        while (dev->num_child_bus) {
320
            bus = QLIST_FIRST(&dev->child_bus);
321
            qbus_free(bus);
322
        }
323
        if (dev->info->vmsd)
324
            vmstate_unregister(dev->info->vmsd, dev);
325
        if (dev->info->exit)
326
            dev->info->exit(dev);
327
        if (dev->opts)
328
            qemu_opts_del(dev->opts);
329
    }
330
    qemu_unregister_reset(qdev_reset, dev);
331
    QLIST_REMOVE(dev, sibling);
332
    qemu_free(dev);
333
}
334

    
335
void qdev_machine_creation_done(void)
336
{
337
    /*
338
     * ok, initial machine setup is done, starting from now we can
339
     * only create hotpluggable devices
340
     */
341
    qdev_hotplug = 1;
342
}
343

    
344
/* Get a character (serial) device interface.  */
345
CharDriverState *qdev_init_chardev(DeviceState *dev)
346
{
347
    static int next_serial;
348

    
349
    /* FIXME: This function needs to go away: use chardev properties!  */
350
    return serial_hds[next_serial++];
351
}
352

    
353
BusState *qdev_get_parent_bus(DeviceState *dev)
354
{
355
    return dev->parent_bus;
356
}
357

    
358
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
359
{
360
    assert(dev->num_gpio_in == 0);
361
    dev->num_gpio_in = n;
362
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
363
}
364

    
365
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
366
{
367
    assert(dev->num_gpio_out == 0);
368
    dev->num_gpio_out = n;
369
    dev->gpio_out = pins;
370
}
371

    
372
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
373
{
374
    assert(n >= 0 && n < dev->num_gpio_in);
375
    return dev->gpio_in[n];
376
}
377

    
378
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
379
{
380
    assert(n >= 0 && n < dev->num_gpio_out);
381
    dev->gpio_out[n] = pin;
382
}
383

    
384
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
385
{
386
    qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
387
    if (nd->vlan)
388
        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
389
    if (nd->netdev)
390
        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
391
    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
392
        qdev_prop_exists(dev, "vectors")) {
393
        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
394
    }
395
}
396

    
397
static int next_block_unit[IF_COUNT];
398

    
399
/* Get a block device.  This should only be used for single-drive devices
400
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
401
   appropriate bus.  */
402
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
403
{
404
    int unit = next_block_unit[type]++;
405
    DriveInfo *dinfo;
406

    
407
    dinfo = drive_get(type, 0, unit);
408
    return dinfo ? dinfo->bdrv : NULL;
409
}
410

    
411
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
412
{
413
    BusState *bus;
414

    
415
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
416
        if (strcmp(name, bus->name) == 0) {
417
            return bus;
418
        }
419
    }
420
    return NULL;
421
}
422

    
423
static BusState *qbus_find_recursive(BusState *bus, const char *name,
424
                                     const BusInfo *info)
425
{
426
    DeviceState *dev;
427
    BusState *child, *ret;
428
    int match = 1;
429

    
430
    if (name && (strcmp(bus->name, name) != 0)) {
431
        match = 0;
432
    }
433
    if (info && (bus->info != info)) {
434
        match = 0;
435
    }
436
    if (match) {
437
        return bus;
438
    }
439

    
440
    QLIST_FOREACH(dev, &bus->children, sibling) {
441
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
442
            ret = qbus_find_recursive(child, name, info);
443
            if (ret) {
444
                return ret;
445
            }
446
        }
447
    }
448
    return NULL;
449
}
450

    
451
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
452
{
453
    DeviceState *dev, *ret;
454
    BusState *child;
455

    
456
    QLIST_FOREACH(dev, &bus->children, sibling) {
457
        if (dev->id && strcmp(dev->id, id) == 0)
458
            return dev;
459
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
460
            ret = qdev_find_recursive(child, id);
461
            if (ret) {
462
                return ret;
463
            }
464
        }
465
    }
466
    return NULL;
467
}
468

    
469
static void qbus_list_bus(DeviceState *dev)
470
{
471
    BusState *child;
472
    const char *sep = " ";
473

    
474
    error_printf("child busses at \"%s\":",
475
                 dev->id ? dev->id : dev->info->name);
476
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
477
        error_printf("%s\"%s\"", sep, child->name);
478
        sep = ", ";
479
    }
480
    error_printf("\n");
481
}
482

    
483
static void qbus_list_dev(BusState *bus)
484
{
485
    DeviceState *dev;
486
    const char *sep = " ";
487

    
488
    error_printf("devices at \"%s\":", bus->name);
489
    QLIST_FOREACH(dev, &bus->children, sibling) {
490
        error_printf("%s\"%s\"", sep, dev->info->name);
491
        if (dev->id)
492
            error_printf("/\"%s\"", dev->id);
493
        sep = ", ";
494
    }
495
    error_printf("\n");
496
}
497

    
498
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
499
{
500
    BusState *child;
501

    
502
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
503
        if (strcmp(child->name, elem) == 0) {
504
            return child;
505
        }
506
    }
507
    return NULL;
508
}
509

    
510
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
511
{
512
    DeviceState *dev;
513

    
514
    /*
515
     * try to match in order:
516
     *   (1) instance id, if present
517
     *   (2) driver name
518
     *   (3) driver alias, if present
519
     */
520
    QLIST_FOREACH(dev, &bus->children, sibling) {
521
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
522
            return dev;
523
        }
524
    }
525
    QLIST_FOREACH(dev, &bus->children, sibling) {
526
        if (strcmp(dev->info->name, elem) == 0) {
527
            return dev;
528
        }
529
    }
530
    QLIST_FOREACH(dev, &bus->children, sibling) {
531
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
532
            return dev;
533
        }
534
    }
535
    return NULL;
536
}
537

    
538
static BusState *qbus_find(const char *path)
539
{
540
    DeviceState *dev;
541
    BusState *bus;
542
    char elem[128];
543
    int pos, len;
544

    
545
    /* find start element */
546
    if (path[0] == '/') {
547
        bus = main_system_bus;
548
        pos = 0;
549
    } else {
550
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
551
            error_report("path parse error (\"%s\")", path);
552
            return NULL;
553
        }
554
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
555
        if (!bus) {
556
            error_report("bus \"%s\" not found", elem);
557
            return NULL;
558
        }
559
        pos = len;
560
    }
561

    
562
    for (;;) {
563
        if (path[pos] == '\0') {
564
            /* we are done */
565
            return bus;
566
        }
567

    
568
        /* find device */
569
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
570
            error_report("path parse error (\"%s\" pos %d)", path, pos);
571
            return NULL;
572
        }
573
        pos += len;
574
        dev = qbus_find_dev(bus, elem);
575
        if (!dev) {
576
            error_report("device \"%s\" not found", elem);
577
            qbus_list_dev(bus);
578
            return NULL;
579
        }
580
        if (path[pos] == '\0') {
581
            /* last specified element is a device.  If it has exactly
582
             * one child bus accept it nevertheless */
583
            switch (dev->num_child_bus) {
584
            case 0:
585
                error_report("device has no child bus (%s)", path);
586
                return NULL;
587
            case 1:
588
                return QLIST_FIRST(&dev->child_bus);
589
            default:
590
                error_report("device has multiple child busses (%s)", path);
591
                qbus_list_bus(dev);
592
                return NULL;
593
            }
594
        }
595

    
596
        /* find bus */
597
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
598
            error_report("path parse error (\"%s\" pos %d)", path, pos);
599
            return NULL;
600
        }
601
        pos += len;
602
        bus = qbus_find_bus(dev, elem);
603
        if (!bus) {
604
            error_report("child bus \"%s\" not found", elem);
605
            qbus_list_bus(dev);
606
            return NULL;
607
        }
608
    }
609
}
610

    
611
void qbus_create_inplace(BusState *bus, BusInfo *info,
612
                         DeviceState *parent, const char *name)
613
{
614
    char *buf;
615
    int i,len;
616

    
617
    bus->info = info;
618
    bus->parent = parent;
619

    
620
    if (name) {
621
        /* use supplied name */
622
        bus->name = qemu_strdup(name);
623
    } else if (parent && parent->id) {
624
        /* parent device has id -> use it for bus name */
625
        len = strlen(parent->id) + 16;
626
        buf = qemu_malloc(len);
627
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
628
        bus->name = buf;
629
    } else {
630
        /* no id -> use lowercase bus type for bus name */
631
        len = strlen(info->name) + 16;
632
        buf = qemu_malloc(len);
633
        len = snprintf(buf, len, "%s.%d", info->name,
634
                       parent ? parent->num_child_bus : 0);
635
        for (i = 0; i < len; i++)
636
            buf[i] = qemu_tolower(buf[i]);
637
        bus->name = buf;
638
    }
639

    
640
    QLIST_INIT(&bus->children);
641
    if (parent) {
642
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
643
        parent->num_child_bus++;
644
    }
645

    
646
}
647

    
648
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
649
{
650
    BusState *bus;
651

    
652
    bus = qemu_mallocz(info->size);
653
    bus->qdev_allocated = 1;
654
    qbus_create_inplace(bus, info, parent, name);
655
    return bus;
656
}
657

    
658
void qbus_free(BusState *bus)
659
{
660
    DeviceState *dev;
661

    
662
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
663
        qdev_free(dev);
664
    }
665
    if (bus->parent) {
666
        QLIST_REMOVE(bus, sibling);
667
        bus->parent->num_child_bus--;
668
    }
669
    if (bus->qdev_allocated) {
670
        qemu_free(bus);
671
    }
672
}
673

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

    
677
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
678
                             const char *prefix, int indent)
679
{
680
    char buf[64];
681

    
682
    if (!props)
683
        return;
684
    while (props->name) {
685
        if (props->info->print) {
686
            props->info->print(dev, props, buf, sizeof(buf));
687
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
688
        }
689
        props++;
690
    }
691
}
692

    
693
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
694
{
695
    BusState *child;
696
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
697
                dev->id ? dev->id : "");
698
    indent += 2;
699
    if (dev->num_gpio_in) {
700
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
701
    }
702
    if (dev->num_gpio_out) {
703
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
704
    }
705
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
706
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
707
    if (dev->parent_bus->info->print_dev)
708
        dev->parent_bus->info->print_dev(mon, dev, indent);
709
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
710
        qbus_print(mon, child, indent);
711
    }
712
}
713

    
714
static void qbus_print(Monitor *mon, BusState *bus, int indent)
715
{
716
    struct DeviceState *dev;
717

    
718
    qdev_printf("bus: %s\n", bus->name);
719
    indent += 2;
720
    qdev_printf("type %s\n", bus->info->name);
721
    QLIST_FOREACH(dev, &bus->children, sibling) {
722
        qdev_print(mon, dev, indent);
723
    }
724
}
725
#undef qdev_printf
726

    
727
void do_info_qtree(Monitor *mon)
728
{
729
    if (main_system_bus)
730
        qbus_print(mon, main_system_bus, 0);
731
}
732

    
733
void do_info_qdm(Monitor *mon)
734
{
735
    DeviceInfo *info;
736

    
737
    for (info = device_info_list; info != NULL; info = info->next) {
738
        qdev_print_devinfo(info);
739
    }
740
}
741

    
742
void do_device_add(Monitor *mon, const QDict *qdict)
743
{
744
    QemuOpts *opts;
745

    
746
    opts = qemu_opts_parse(&qemu_device_opts,
747
                           qdict_get_str(qdict, "config"), "driver");
748
    if (opts) {
749
        if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
750
            qemu_opts_del(opts);
751
        }
752
    }
753
}
754

    
755
void do_device_del(Monitor *mon, const QDict *qdict)
756
{
757
    const char *id = qdict_get_str(qdict, "id");
758
    DeviceState *dev;
759

    
760
    dev = qdev_find_recursive(main_system_bus, id);
761
    if (NULL == dev) {
762
        error_report("Device '%s' not found", id);
763
        return;
764
    }
765
    qdev_unplug(dev);
766
}