Statistics
| Branch: | Revision:

root / hw / qdev.c @ 44a99354

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

    
33
static int qdev_hotplug = 0;
34

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

    
38
DeviceInfo *device_info_list;
39

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

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

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

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

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

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

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

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

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

    
100
    dev = qemu_mallocz(info->size);
101
    dev->info = info;
102
    dev->parent_bus = bus;
103
    qdev_prop_set_defaults(dev, dev->info->props);
104
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
105
    qdev_prop_set_compat(dev);
106
    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
107
    if (qdev_hotplug) {
108
        assert(bus->allow_hotplug);
109
        dev->hotplugged = 1;
110
    }
111
    dev->state = DEV_STATE_CREATED;
112
    return dev;
113
}
114

    
115
static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
116
{
117
    int pos = 0;
118
    int ret;
119

    
120
    ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
121
                   info->name, info->bus_info->name);
122
    pos += MIN(len-pos,ret);
123
    if (info->alias) {
124
        ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
125
        pos += MIN(len-pos,ret);
126
    }
127
    if (info->desc) {
128
        ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
129
        pos += MIN(len-pos,ret);
130
    }
131
    if (info->no_user) {
132
        ret = snprintf(dest+pos, len-pos, ", no-user");
133
        pos += MIN(len-pos,ret);
134
    }
135
    return pos;
136
}
137

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

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

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

    
155
DeviceState *qdev_device_add(QemuOpts *opts)
156
{
157
    const char *driver, *path, *id;
158
    DeviceInfo *info;
159
    DeviceState *qdev;
160
    BusState *bus;
161

    
162
    driver = qemu_opt_get(opts, "driver");
163
    if (!driver) {
164
        qemu_error("-device: no driver specified\n");
165
        return NULL;
166
    }
167
    if (strcmp(driver, "?") == 0) {
168
        char msg[256];
169
        for (info = device_info_list; info != NULL; info = info->next) {
170
            qdev_print_devinfo(info, msg, sizeof(msg));
171
            qemu_error("%s\n", msg);
172
        }
173
        return NULL;
174
    }
175

    
176
    /* find driver */
177
    info = qdev_find_info(NULL, driver);
178
    if (!info) {
179
        qemu_error("Device \"%s\" not found.  Try -device '?' for a list.\n",
180
                   driver);
181
        return NULL;
182
    }
183
    if (info->no_user) {
184
        qemu_error("device \"%s\" can't be added via command line\n",
185
                   info->name);
186
        return NULL;
187
    }
188

    
189
    /* find bus */
190
    path = qemu_opt_get(opts, "bus");
191
    if (path != NULL) {
192
        bus = qbus_find(path);
193
    } else {
194
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
195
    }
196
    if (!bus) {
197
        qemu_error("Did not find %s bus for %s\n",
198
                   path ? path : info->bus_info->name, info->name);
199
        return NULL;
200
    }
201
    if (qdev_hotplug && !bus->allow_hotplug) {
202
        qemu_error("Bus %s does not support hotplugging\n",
203
                   bus->name);
204
        return NULL;
205
    }
206

    
207
    /* create device, set properties */
208
    qdev = qdev_create(bus, driver);
209
    id = qemu_opts_id(opts);
210
    if (id) {
211
        qdev->id = id;
212
    }
213
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
214
        qdev_free(qdev);
215
        return NULL;
216
    }
217
    if (qdev_init(qdev) < 0) {
218
        qemu_error("Error initializing device %s\n", driver);
219
        return NULL;
220
    }
221
    qdev->opts = opts;
222
    return qdev;
223
}
224

    
225
static void qdev_reset(void *opaque)
226
{
227
    DeviceState *dev = opaque;
228
    if (dev->info->reset)
229
        dev->info->reset(dev);
230
}
231

    
232
/* Initialize a device.  Device properties should be set before calling
233
   this function.  IRQs and MMIO regions should be connected/mapped after
234
   calling this function.
235
   On failure, destroy the device and return negative value.
236
   Return 0 on success.  */
237
int qdev_init(DeviceState *dev)
238
{
239
    int rc;
240

    
241
    assert(dev->state == DEV_STATE_CREATED);
242
    rc = dev->info->init(dev, dev->info);
243
    if (rc < 0) {
244
        qdev_free(dev);
245
        return rc;
246
    }
247
    qemu_register_reset(qdev_reset, dev);
248
    if (dev->info->vmsd)
249
        vmstate_register(-1, dev->info->vmsd, dev);
250
    dev->state = DEV_STATE_INITIALIZED;
251
    return 0;
252
}
253

    
254
int qdev_unplug(DeviceState *dev)
255
{
256
    if (!dev->parent_bus->allow_hotplug) {
257
        qemu_error("Bus %s does not support hotplugging\n",
258
                   dev->parent_bus->name);
259
        return -1;
260
    }
261
    return dev->info->unplug(dev);
262
}
263

    
264
/* can be used as ->unplug() callback for the simple cases */
265
int qdev_simple_unplug_cb(DeviceState *dev)
266
{
267
    /* just zap it */
268
    qdev_free(dev);
269
    return 0;
270
}
271

    
272
/* Like qdev_init(), but terminate program via hw_error() instead of
273
   returning an error value.  This is okay during machine creation.
274
   Don't use for hotplug, because there callers need to recover from
275
   failure.  Exception: if you know the device's init() callback can't
276
   fail, then qdev_init_nofail() can't fail either, and is therefore
277
   usable even then.  But relying on the device implementation that
278
   way is somewhat unclean, and best avoided.  */
279
void qdev_init_nofail(DeviceState *dev)
280
{
281
    DeviceInfo *info = dev->info;
282

    
283
    if (qdev_init(dev) < 0)
284
        hw_error("Initialization of device %s failed\n", info->name);
285
}
286

    
287
/* Unlink device from bus and free the structure.  */
288
void qdev_free(DeviceState *dev)
289
{
290
    BusState *bus;
291

    
292
    if (dev->state == DEV_STATE_INITIALIZED) {
293
        while (dev->num_child_bus) {
294
            bus = QLIST_FIRST(&dev->child_bus);
295
            qbus_free(bus);
296
        }
297
#if 0 /* FIXME: need sane vmstate_unregister function */
298
        if (dev->info->vmsd)
299
            vmstate_unregister(dev->info->vmsd, dev);
300
#endif
301
        if (dev->info->exit)
302
            dev->info->exit(dev);
303
        if (dev->opts)
304
            qemu_opts_del(dev->opts);
305
    }
306
    qemu_unregister_reset(qdev_reset, dev);
307
    QLIST_REMOVE(dev, sibling);
308
    qemu_free(dev);
309
}
310

    
311
void qdev_machine_creation_done(void)
312
{
313
    /*
314
     * ok, initial machine setup is done, starting from now we can
315
     * only create hotpluggable devices
316
     */
317
    qdev_hotplug = 1;
318
}
319

    
320
/* Get a character (serial) device interface.  */
321
CharDriverState *qdev_init_chardev(DeviceState *dev)
322
{
323
    static int next_serial;
324
    static int next_virtconsole;
325
    /* FIXME: This is a nasty hack that needs to go away.  */
326
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
327
        return virtcon_hds[next_virtconsole++];
328
    } else {
329
        return serial_hds[next_serial++];
330
    }
331
}
332

    
333
BusState *qdev_get_parent_bus(DeviceState *dev)
334
{
335
    return dev->parent_bus;
336
}
337

    
338
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
339
{
340
    assert(dev->num_gpio_in == 0);
341
    dev->num_gpio_in = n;
342
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
343
}
344

    
345
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
346
{
347
    assert(dev->num_gpio_out == 0);
348
    dev->num_gpio_out = n;
349
    dev->gpio_out = pins;
350
}
351

    
352
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
353
{
354
    assert(n >= 0 && n < dev->num_gpio_in);
355
    return dev->gpio_in[n];
356
}
357

    
358
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
359
{
360
    assert(n >= 0 && n < dev->num_gpio_out);
361
    dev->gpio_out[n] = pin;
362
}
363

    
364
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
365
{
366
    qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
367
    if (nd->vlan)
368
        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
369
    if (nd->netdev)
370
        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
371
    if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
372
        qdev_prop_exists(dev, "vectors")) {
373
        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
374
    }
375
}
376

    
377
static int next_block_unit[IF_COUNT];
378

    
379
/* Get a block device.  This should only be used for single-drive devices
380
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
381
   appropriate bus.  */
382
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
383
{
384
    int unit = next_block_unit[type]++;
385
    DriveInfo *dinfo;
386

    
387
    dinfo = drive_get(type, 0, unit);
388
    return dinfo ? dinfo->bdrv : NULL;
389
}
390

    
391
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
392
{
393
    BusState *bus;
394

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

    
403
static BusState *qbus_find_recursive(BusState *bus, const char *name,
404
                                     const BusInfo *info)
405
{
406
    DeviceState *dev;
407
    BusState *child, *ret;
408
    int match = 1;
409

    
410
    if (name && (strcmp(bus->name, name) != 0)) {
411
        match = 0;
412
    }
413
    if (info && (bus->info != info)) {
414
        match = 0;
415
    }
416
    if (match) {
417
        return bus;
418
    }
419

    
420
    QLIST_FOREACH(dev, &bus->children, sibling) {
421
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
422
            ret = qbus_find_recursive(child, name, info);
423
            if (ret) {
424
                return ret;
425
            }
426
        }
427
    }
428
    return NULL;
429
}
430

    
431
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
432
{
433
    DeviceState *dev, *ret;
434
    BusState *child;
435

    
436
    QLIST_FOREACH(dev, &bus->children, sibling) {
437
        if (dev->id && strcmp(dev->id, id) == 0)
438
            return dev;
439
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
440
            ret = qdev_find_recursive(child, id);
441
            if (ret) {
442
                return ret;
443
            }
444
        }
445
    }
446
    return NULL;
447
}
448

    
449
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
450
{
451
    BusState *child;
452
    const char *sep = " ";
453
    int pos = 0;
454

    
455
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
456
                    dev->id ? dev->id : dev->info->name);
457
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
458
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
459
        sep = ", ";
460
    }
461
}
462

    
463
static void qbus_list_dev(BusState *bus, char *dest, int len)
464
{
465
    DeviceState *dev;
466
    const char *sep = " ";
467
    int pos = 0;
468

    
469
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
470
                    bus->name);
471
    QLIST_FOREACH(dev, &bus->children, sibling) {
472
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
473
                        sep, dev->info->name);
474
        if (dev->id)
475
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
476
        sep = ", ";
477
    }
478
}
479

    
480
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
481
{
482
    BusState *child;
483

    
484
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
485
        if (strcmp(child->name, elem) == 0) {
486
            return child;
487
        }
488
    }
489
    return NULL;
490
}
491

    
492
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
493
{
494
    DeviceState *dev;
495

    
496
    /*
497
     * try to match in order:
498
     *   (1) instance id, if present
499
     *   (2) driver name
500
     *   (3) driver alias, if present
501
     */
502
    QLIST_FOREACH(dev, &bus->children, sibling) {
503
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
504
            return dev;
505
        }
506
    }
507
    QLIST_FOREACH(dev, &bus->children, sibling) {
508
        if (strcmp(dev->info->name, elem) == 0) {
509
            return dev;
510
        }
511
    }
512
    QLIST_FOREACH(dev, &bus->children, sibling) {
513
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
514
            return dev;
515
        }
516
    }
517
    return NULL;
518
}
519

    
520
static BusState *qbus_find(const char *path)
521
{
522
    DeviceState *dev;
523
    BusState *bus;
524
    char elem[128], msg[256];
525
    int pos, len;
526

    
527
    /* find start element */
528
    if (path[0] == '/') {
529
        bus = main_system_bus;
530
        pos = 0;
531
    } else {
532
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
533
            qemu_error("path parse error (\"%s\")\n", path);
534
            return NULL;
535
        }
536
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
537
        if (!bus) {
538
            qemu_error("bus \"%s\" not found\n", elem);
539
            return NULL;
540
        }
541
        pos = len;
542
    }
543

    
544
    for (;;) {
545
        if (path[pos] == '\0') {
546
            /* we are done */
547
            return bus;
548
        }
549

    
550
        /* find device */
551
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
552
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
553
            return NULL;
554
        }
555
        pos += len;
556
        dev = qbus_find_dev(bus, elem);
557
        if (!dev) {
558
            qbus_list_dev(bus, msg, sizeof(msg));
559
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
560
            return NULL;
561
        }
562
        if (path[pos] == '\0') {
563
            /* last specified element is a device.  If it has exactly
564
             * one child bus accept it nevertheless */
565
            switch (dev->num_child_bus) {
566
            case 0:
567
                qemu_error("device has no child bus (%s)\n", path);
568
                return NULL;
569
            case 1:
570
                return QLIST_FIRST(&dev->child_bus);
571
            default:
572
                qbus_list_bus(dev, msg, sizeof(msg));
573
                qemu_error("device has multiple child busses (%s)\n%s\n",
574
                           path, msg);
575
                return NULL;
576
            }
577
        }
578

    
579
        /* find bus */
580
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
581
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
582
            return NULL;
583
        }
584
        pos += len;
585
        bus = qbus_find_bus(dev, elem);
586
        if (!bus) {
587
            qbus_list_bus(dev, msg, sizeof(msg));
588
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
589
            return NULL;
590
        }
591
    }
592
}
593

    
594
void qbus_create_inplace(BusState *bus, BusInfo *info,
595
                         DeviceState *parent, const char *name)
596
{
597
    char *buf;
598
    int i,len;
599

    
600
    bus->info = info;
601
    bus->parent = parent;
602

    
603
    if (name) {
604
        /* use supplied name */
605
        bus->name = qemu_strdup(name);
606
    } else if (parent && parent->id) {
607
        /* parent device has id -> use it for bus name */
608
        len = strlen(parent->id) + 16;
609
        buf = qemu_malloc(len);
610
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
611
        bus->name = buf;
612
    } else {
613
        /* no id -> use lowercase bus type for bus name */
614
        len = strlen(info->name) + 16;
615
        buf = qemu_malloc(len);
616
        len = snprintf(buf, len, "%s.%d", info->name,
617
                       parent ? parent->num_child_bus : 0);
618
        for (i = 0; i < len; i++)
619
            buf[i] = qemu_tolower(buf[i]);
620
        bus->name = buf;
621
    }
622

    
623
    QLIST_INIT(&bus->children);
624
    if (parent) {
625
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
626
        parent->num_child_bus++;
627
    }
628

    
629
}
630

    
631
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
632
{
633
    BusState *bus;
634

    
635
    bus = qemu_mallocz(info->size);
636
    bus->qdev_allocated = 1;
637
    qbus_create_inplace(bus, info, parent, name);
638
    return bus;
639
}
640

    
641
void qbus_free(BusState *bus)
642
{
643
    DeviceState *dev;
644

    
645
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
646
        qdev_free(dev);
647
    }
648
    if (bus->parent) {
649
        QLIST_REMOVE(bus, sibling);
650
        bus->parent->num_child_bus--;
651
    }
652
    if (bus->qdev_allocated) {
653
        qemu_free(bus);
654
    }
655
}
656

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

    
660
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
661
                             const char *prefix, int indent)
662
{
663
    char buf[64];
664

    
665
    if (!props)
666
        return;
667
    while (props->name) {
668
        if (props->info->print) {
669
            props->info->print(dev, props, buf, sizeof(buf));
670
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
671
        }
672
        props++;
673
    }
674
}
675

    
676
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
677
{
678
    BusState *child;
679
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
680
                dev->id ? dev->id : "");
681
    indent += 2;
682
    if (dev->num_gpio_in) {
683
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
684
    }
685
    if (dev->num_gpio_out) {
686
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
687
    }
688
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
689
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
690
    if (dev->parent_bus->info->print_dev)
691
        dev->parent_bus->info->print_dev(mon, dev, indent);
692
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
693
        qbus_print(mon, child, indent);
694
    }
695
}
696

    
697
static void qbus_print(Monitor *mon, BusState *bus, int indent)
698
{
699
    struct DeviceState *dev;
700

    
701
    qdev_printf("bus: %s\n", bus->name);
702
    indent += 2;
703
    qdev_printf("type %s\n", bus->info->name);
704
    QLIST_FOREACH(dev, &bus->children, sibling) {
705
        qdev_print(mon, dev, indent);
706
    }
707
}
708
#undef qdev_printf
709

    
710
void do_info_qtree(Monitor *mon)
711
{
712
    if (main_system_bus)
713
        qbus_print(mon, main_system_bus, 0);
714
}
715

    
716
void do_info_qdm(Monitor *mon)
717
{
718
    DeviceInfo *info;
719
    char msg[256];
720

    
721
    for (info = device_info_list; info != NULL; info = info->next) {
722
        qdev_print_devinfo(info, msg, sizeof(msg));
723
        monitor_printf(mon, "%s\n", msg);
724
    }
725
}
726

    
727
void do_device_add(Monitor *mon, const QDict *qdict)
728
{
729
    QemuOpts *opts;
730

    
731
    opts = qemu_opts_parse(&qemu_device_opts,
732
                           qdict_get_str(qdict, "config"), "driver");
733
    if (opts)
734
        qdev_device_add(opts);
735
}
736

    
737
void do_device_del(Monitor *mon, const QDict *qdict)
738
{
739
    const char *id = qdict_get_str(qdict, "id");
740
    DeviceState *dev;
741

    
742
    dev = qdev_find_recursive(main_system_bus, id);
743
    if (NULL == dev) {
744
        qemu_error("Device '%s' not found\n", id);
745
        return;
746
    }
747
    qdev_unplug(dev);
748
}