Statistics
| Branch: | Revision:

root / hw / qdev.c @ 7f23f812

History | View | Annotate | Download (19.8 kB)

1
/*
2
 *  Dynamic device configuration and creation.
3
 *
4
 *  Copyright (c) 2009 CodeSourcery
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, 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 int qdev_hotplug = 0;
35

    
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
        qdev_free(qdev);
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
int qdev_init(DeviceState *dev)
236
{
237
    int rc;
238

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

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

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

    
268
/* Unlink device from bus and free the structure.  */
269
void qdev_free(DeviceState *dev)
270
{
271
    BusState *bus;
272

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

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

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

    
314
BusState *qdev_get_parent_bus(DeviceState *dev)
315
{
316
    return dev->parent_bus;
317
}
318

    
319
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
320
{
321
    assert(dev->num_gpio_in == 0);
322
    dev->num_gpio_in = n;
323
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
324
}
325

    
326
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
327
{
328
    assert(dev->num_gpio_out == 0);
329
    dev->num_gpio_out = n;
330
    dev->gpio_out = pins;
331
}
332

    
333
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
334
{
335
    assert(n >= 0 && n < dev->num_gpio_in);
336
    return dev->gpio_in[n];
337
}
338

    
339
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
340
{
341
    assert(n >= 0 && n < dev->num_gpio_out);
342
    dev->gpio_out[n] = pin;
343
}
344

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

    
359

    
360
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
361
{
362
    memcpy(macaddr, dev->nd->macaddr, 6);
363
}
364

    
365
static int next_block_unit[IF_COUNT];
366

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

    
375
    dinfo = drive_get(type, 0, unit);
376
    return dinfo ? dinfo->bdrv : NULL;
377
}
378

    
379
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
380
{
381
    BusState *bus;
382

    
383
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
384
        if (strcmp(name, bus->name) == 0) {
385
            return bus;
386
        }
387
    }
388
    return NULL;
389
}
390

    
391
static BusState *qbus_find_recursive(BusState *bus, const char *name,
392
                                     const BusInfo *info)
393
{
394
    DeviceState *dev;
395
    BusState *child, *ret;
396
    int match = 1;
397

    
398
    if (name && (strcmp(bus->name, name) != 0)) {
399
        match = 0;
400
    }
401
    if (info && (bus->info != info)) {
402
        match = 0;
403
    }
404
    if (match) {
405
        return bus;
406
    }
407

    
408
    QLIST_FOREACH(dev, &bus->children, sibling) {
409
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
410
            ret = qbus_find_recursive(child, name, info);
411
            if (ret) {
412
                return ret;
413
            }
414
        }
415
    }
416
    return NULL;
417
}
418

    
419
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
420
{
421
    DeviceState *dev, *ret;
422
    BusState *child;
423

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

    
437
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
438
{
439
    BusState *child;
440
    const char *sep = " ";
441
    int pos = 0;
442

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

    
451
static void qbus_list_dev(BusState *bus, char *dest, int len)
452
{
453
    DeviceState *dev;
454
    const char *sep = " ";
455
    int pos = 0;
456

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

    
468
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
469
{
470
    BusState *child;
471

    
472
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
473
        if (strcmp(child->name, elem) == 0) {
474
            return child;
475
        }
476
    }
477
    return NULL;
478
}
479

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

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

    
508
static BusState *qbus_find(const char *path)
509
{
510
    DeviceState *dev;
511
    BusState *bus;
512
    char elem[128], msg[256];
513
    int pos, len;
514

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

    
532
    for (;;) {
533
        if (path[pos] == '\0') {
534
            /* we are done */
535
            return bus;
536
        }
537

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

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

    
582
void qbus_create_inplace(BusState *bus, BusInfo *info,
583
                         DeviceState *parent, const char *name)
584
{
585
    char *buf;
586
    int i,len;
587

    
588
    bus->info = info;
589
    bus->parent = parent;
590

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

    
611
    QLIST_INIT(&bus->children);
612
    if (parent) {
613
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
614
        parent->num_child_bus++;
615
    }
616

    
617
}
618

    
619
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
620
{
621
    BusState *bus;
622

    
623
    bus = qemu_mallocz(info->size);
624
    bus->qdev_allocated = 1;
625
    qbus_create_inplace(bus, info, parent, name);
626
    return bus;
627
}
628

    
629
void qbus_free(BusState *bus)
630
{
631
    DeviceState *dev;
632

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

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

    
648
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
649
                             const char *prefix, int indent)
650
{
651
    char buf[64];
652

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

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

    
685
static void qbus_print(Monitor *mon, BusState *bus, int indent)
686
{
687
    struct DeviceState *dev;
688

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

    
698
void do_info_qtree(Monitor *mon)
699
{
700
    if (main_system_bus)
701
        qbus_print(mon, main_system_bus, 0);
702
}
703

    
704
void do_info_qdm(Monitor *mon)
705
{
706
    DeviceInfo *info;
707
    char msg[256];
708

    
709
    for (info = device_info_list; info != NULL; info = info->next) {
710
        qdev_print_devinfo(info, msg, sizeof(msg));
711
        monitor_printf(mon, "%s\n", msg);
712
    }
713
}
714

    
715
void do_device_add(Monitor *mon, const QDict *qdict)
716
{
717
    QemuOpts *opts;
718

    
719
    opts = qemu_opts_parse(&qemu_device_opts,
720
                           qdict_get_str(qdict, "config"), "driver");
721
    if (opts)
722
        qdev_device_add(opts);
723
}
724

    
725
void do_device_del(Monitor *mon, const QDict *qdict)
726
{
727
    const char *id = qdict_get_str(qdict, "id");
728
    DeviceState *dev;
729

    
730
    dev = qdev_find_recursive(main_system_bus, id);
731
    if (NULL == dev) {
732
        qemu_error("Device '%s' not found\n", id);
733
        return;
734
    }
735
    qdev_unplug(dev);
736
}