Statistics
| Branch: | Revision:

root / hw / qdev.c @ 18cfeb52

History | View | Annotate | Download (19.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
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
static 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
/* Unlink device from bus and free the structure.  */
273
void qdev_free(DeviceState *dev)
274
{
275
    BusState *bus;
276

    
277
    if (dev->state == DEV_STATE_INITIALIZED) {
278
        while (dev->num_child_bus) {
279
            bus = QLIST_FIRST(&dev->child_bus);
280
            qbus_free(bus);
281
        }
282
#if 0 /* FIXME: need sane vmstate_unregister function */
283
        if (dev->info->vmsd)
284
            vmstate_unregister(dev->info->vmsd, dev);
285
#endif
286
        if (dev->info->exit)
287
            dev->info->exit(dev);
288
        if (dev->opts)
289
            qemu_opts_del(dev->opts);
290
    }
291
    qemu_unregister_reset(qdev_reset, dev);
292
    QLIST_REMOVE(dev, sibling);
293
    qemu_free(dev);
294
}
295

    
296
void qdev_machine_creation_done(void)
297
{
298
    /*
299
     * ok, initial machine setup is done, starting from now we can
300
     * only create hotpluggable devices
301
     */
302
    qdev_hotplug = 1;
303
}
304

    
305
/* Get a character (serial) device interface.  */
306
CharDriverState *qdev_init_chardev(DeviceState *dev)
307
{
308
    static int next_serial;
309
    static int next_virtconsole;
310
    /* FIXME: This is a nasty hack that needs to go away.  */
311
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
312
        return virtcon_hds[next_virtconsole++];
313
    } else {
314
        return serial_hds[next_serial++];
315
    }
316
}
317

    
318
BusState *qdev_get_parent_bus(DeviceState *dev)
319
{
320
    return dev->parent_bus;
321
}
322

    
323
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
324
{
325
    assert(dev->num_gpio_in == 0);
326
    dev->num_gpio_in = n;
327
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
328
}
329

    
330
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
331
{
332
    assert(dev->num_gpio_out == 0);
333
    dev->num_gpio_out = n;
334
    dev->gpio_out = pins;
335
}
336

    
337
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
338
{
339
    assert(n >= 0 && n < dev->num_gpio_in);
340
    return dev->gpio_in[n];
341
}
342

    
343
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
344
{
345
    assert(n >= 0 && n < dev->num_gpio_out);
346
    dev->gpio_out[n] = pin;
347
}
348

    
349
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
350
                                      NetCanReceive *can_receive,
351
                                      NetReceive *receive,
352
                                      NetReceiveIOV *receive_iov,
353
                                      NetCleanup *cleanup,
354
                                      void *opaque)
355
{
356
    NICInfo *nd = dev->nd;
357
    assert(nd);
358
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
359
                                  receive, receive_iov, cleanup, opaque);
360
    return nd->vc;
361
}
362

    
363

    
364
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
365
{
366
    memcpy(macaddr, dev->nd->macaddr, 6);
367
}
368

    
369
static int next_block_unit[IF_COUNT];
370

    
371
/* Get a block device.  This should only be used for single-drive devices
372
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
373
   appropriate bus.  */
374
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
375
{
376
    int unit = next_block_unit[type]++;
377
    DriveInfo *dinfo;
378

    
379
    dinfo = drive_get(type, 0, unit);
380
    return dinfo ? dinfo->bdrv : NULL;
381
}
382

    
383
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
384
{
385
    BusState *bus;
386

    
387
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
388
        if (strcmp(name, bus->name) == 0) {
389
            return bus;
390
        }
391
    }
392
    return NULL;
393
}
394

    
395
static BusState *qbus_find_recursive(BusState *bus, const char *name,
396
                                     const BusInfo *info)
397
{
398
    DeviceState *dev;
399
    BusState *child, *ret;
400
    int match = 1;
401

    
402
    if (name && (strcmp(bus->name, name) != 0)) {
403
        match = 0;
404
    }
405
    if (info && (bus->info != info)) {
406
        match = 0;
407
    }
408
    if (match) {
409
        return bus;
410
    }
411

    
412
    QLIST_FOREACH(dev, &bus->children, sibling) {
413
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
414
            ret = qbus_find_recursive(child, name, info);
415
            if (ret) {
416
                return ret;
417
            }
418
        }
419
    }
420
    return NULL;
421
}
422

    
423
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
424
{
425
    DeviceState *dev, *ret;
426
    BusState *child;
427

    
428
    QLIST_FOREACH(dev, &bus->children, sibling) {
429
        if (dev->id && strcmp(dev->id, id) == 0)
430
            return dev;
431
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
432
            ret = qdev_find_recursive(child, id);
433
            if (ret) {
434
                return ret;
435
            }
436
        }
437
    }
438
    return NULL;
439
}
440

    
441
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
442
{
443
    BusState *child;
444
    const char *sep = " ";
445
    int pos = 0;
446

    
447
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
448
                    dev->id ? dev->id : dev->info->name);
449
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
450
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
451
        sep = ", ";
452
    }
453
}
454

    
455
static void qbus_list_dev(BusState *bus, char *dest, int len)
456
{
457
    DeviceState *dev;
458
    const char *sep = " ";
459
    int pos = 0;
460

    
461
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
462
                    bus->name);
463
    QLIST_FOREACH(dev, &bus->children, sibling) {
464
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
465
                        sep, dev->info->name);
466
        if (dev->id)
467
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
468
        sep = ", ";
469
    }
470
}
471

    
472
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
473
{
474
    BusState *child;
475

    
476
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
477
        if (strcmp(child->name, elem) == 0) {
478
            return child;
479
        }
480
    }
481
    return NULL;
482
}
483

    
484
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
485
{
486
    DeviceState *dev;
487

    
488
    /*
489
     * try to match in order:
490
     *   (1) instance id, if present
491
     *   (2) driver name
492
     *   (3) driver alias, if present
493
     */
494
    QLIST_FOREACH(dev, &bus->children, sibling) {
495
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
496
            return dev;
497
        }
498
    }
499
    QLIST_FOREACH(dev, &bus->children, sibling) {
500
        if (strcmp(dev->info->name, elem) == 0) {
501
            return dev;
502
        }
503
    }
504
    QLIST_FOREACH(dev, &bus->children, sibling) {
505
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
506
            return dev;
507
        }
508
    }
509
    return NULL;
510
}
511

    
512
static BusState *qbus_find(const char *path)
513
{
514
    DeviceState *dev;
515
    BusState *bus;
516
    char elem[128], msg[256];
517
    int pos, len;
518

    
519
    /* find start element */
520
    if (path[0] == '/') {
521
        bus = main_system_bus;
522
        pos = 0;
523
    } else {
524
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
525
            qemu_error("path parse error (\"%s\")\n", path);
526
            return NULL;
527
        }
528
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
529
        if (!bus) {
530
            qemu_error("bus \"%s\" not found\n", elem);
531
            return NULL;
532
        }
533
        pos = len;
534
    }
535

    
536
    for (;;) {
537
        if (path[pos] == '\0') {
538
            /* we are done */
539
            return bus;
540
        }
541

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

    
571
        /* find bus */
572
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
573
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
574
            return NULL;
575
        }
576
        pos += len;
577
        bus = qbus_find_bus(dev, elem);
578
        if (!bus) {
579
            qbus_list_bus(dev, msg, sizeof(msg));
580
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
581
            return NULL;
582
        }
583
    }
584
}
585

    
586
void qbus_create_inplace(BusState *bus, BusInfo *info,
587
                         DeviceState *parent, const char *name)
588
{
589
    char *buf;
590
    int i,len;
591

    
592
    bus->info = info;
593
    bus->parent = parent;
594

    
595
    if (name) {
596
        /* use supplied name */
597
        bus->name = qemu_strdup(name);
598
    } else if (parent && parent->id) {
599
        /* parent device has id -> use it for bus name */
600
        len = strlen(parent->id) + 16;
601
        buf = qemu_malloc(len);
602
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
603
        bus->name = buf;
604
    } else {
605
        /* no id -> use lowercase bus type for bus name */
606
        len = strlen(info->name) + 16;
607
        buf = qemu_malloc(len);
608
        len = snprintf(buf, len, "%s.%d", info->name,
609
                       parent ? parent->num_child_bus : 0);
610
        for (i = 0; i < len; i++)
611
            buf[i] = qemu_tolower(buf[i]);
612
        bus->name = buf;
613
    }
614

    
615
    QLIST_INIT(&bus->children);
616
    if (parent) {
617
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
618
        parent->num_child_bus++;
619
    }
620

    
621
}
622

    
623
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
624
{
625
    BusState *bus;
626

    
627
    bus = qemu_mallocz(info->size);
628
    bus->qdev_allocated = 1;
629
    qbus_create_inplace(bus, info, parent, name);
630
    return bus;
631
}
632

    
633
void qbus_free(BusState *bus)
634
{
635
    DeviceState *dev;
636

    
637
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
638
        qdev_free(dev);
639
    }
640
    if (bus->parent) {
641
        QLIST_REMOVE(bus, sibling);
642
        bus->parent->num_child_bus--;
643
    }
644
    if (bus->qdev_allocated) {
645
        qemu_free(bus);
646
    }
647
}
648

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

    
652
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
653
                             const char *prefix, int indent)
654
{
655
    char buf[64];
656

    
657
    if (!props)
658
        return;
659
    while (props->name) {
660
        if (props->info->print) {
661
            props->info->print(dev, props, buf, sizeof(buf));
662
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
663
        }
664
        props++;
665
    }
666
}
667

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

    
689
static void qbus_print(Monitor *mon, BusState *bus, int indent)
690
{
691
    struct DeviceState *dev;
692

    
693
    qdev_printf("bus: %s\n", bus->name);
694
    indent += 2;
695
    qdev_printf("type %s\n", bus->info->name);
696
    QLIST_FOREACH(dev, &bus->children, sibling) {
697
        qdev_print(mon, dev, indent);
698
    }
699
}
700
#undef qdev_printf
701

    
702
void do_info_qtree(Monitor *mon)
703
{
704
    if (main_system_bus)
705
        qbus_print(mon, main_system_bus, 0);
706
}
707

    
708
void do_info_qdm(Monitor *mon)
709
{
710
    DeviceInfo *info;
711
    char msg[256];
712

    
713
    for (info = device_info_list; info != NULL; info = info->next) {
714
        qdev_print_devinfo(info, msg, sizeof(msg));
715
        monitor_printf(mon, "%s\n", msg);
716
    }
717
}
718

    
719
void do_device_add(Monitor *mon, const QDict *qdict)
720
{
721
    QemuOpts *opts;
722

    
723
    opts = qemu_opts_parse(&qemu_device_opts,
724
                           qdict_get_str(qdict, "config"), "driver");
725
    if (opts)
726
        qdev_device_add(opts);
727
}
728

    
729
void do_device_del(Monitor *mon, const QDict *qdict)
730
{
731
    const char *id = qdict_get_str(qdict, "id");
732
    DeviceState *dev;
733

    
734
    dev = qdev_find_recursive(main_system_bus, id);
735
    if (NULL == dev) {
736
        qemu_error("Device '%s' not found\n", id);
737
        return;
738
    }
739
    qdev_unplug(dev);
740
}