Statistics
| Branch: | Revision:

root / hw / qdev.c @ d29275f1

History | View | Annotate | Download (17.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 BusState *main_system_bus;
35

    
36
static DeviceInfo *device_info_list;
37

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
220
    assert(dev->state == DEV_STATE_CREATED);
221
    rc = dev->info->init(dev, dev->info);
222
    if (rc < 0)
223
        return rc;
224
    if (dev->info->reset)
225
        qemu_register_reset(dev->info->reset, dev);
226
    if (dev->info->vmsd)
227
        vmstate_register(-1, dev->info->vmsd, dev);
228
    dev->state = DEV_STATE_INITIALIZED;
229
    return 0;
230
}
231

    
232
/* Unlink device from bus and free the structure.  */
233
void qdev_free(DeviceState *dev)
234
{
235
    BusState *bus;
236

    
237
    if (dev->state == DEV_STATE_INITIALIZED) {
238
        while (dev->num_child_bus) {
239
            bus = QLIST_FIRST(&dev->child_bus);
240
            qbus_free(bus);
241
        }
242
#if 0 /* FIXME: need sane vmstate_unregister function */
243
        if (dev->info->vmsd)
244
            vmstate_unregister(dev->info->vmsd, dev);
245
#endif
246
        if (dev->info->reset)
247
            qemu_unregister_reset(dev->info->reset, dev);
248
        if (dev->info->exit)
249
            dev->info->exit(dev);
250
    }
251
    QLIST_REMOVE(dev, sibling);
252
    qemu_free(dev);
253
}
254

    
255
/* Get a character (serial) device interface.  */
256
CharDriverState *qdev_init_chardev(DeviceState *dev)
257
{
258
    static int next_serial;
259
    static int next_virtconsole;
260
    /* FIXME: This is a nasty hack that needs to go away.  */
261
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
262
        return virtcon_hds[next_virtconsole++];
263
    } else {
264
        return serial_hds[next_serial++];
265
    }
266
}
267

    
268
BusState *qdev_get_parent_bus(DeviceState *dev)
269
{
270
    return dev->parent_bus;
271
}
272

    
273
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
274
{
275
    assert(dev->num_gpio_in == 0);
276
    dev->num_gpio_in = n;
277
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
278
}
279

    
280
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
281
{
282
    assert(dev->num_gpio_out == 0);
283
    dev->num_gpio_out = n;
284
    dev->gpio_out = pins;
285
}
286

    
287
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
288
{
289
    assert(n >= 0 && n < dev->num_gpio_in);
290
    return dev->gpio_in[n];
291
}
292

    
293
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
294
{
295
    assert(n >= 0 && n < dev->num_gpio_out);
296
    dev->gpio_out[n] = pin;
297
}
298

    
299
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
300
                                      NetCanReceive *can_receive,
301
                                      NetReceive *receive,
302
                                      NetReceiveIOV *receive_iov,
303
                                      NetCleanup *cleanup,
304
                                      void *opaque)
305
{
306
    NICInfo *nd = dev->nd;
307
    assert(nd);
308
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
309
                                  receive, receive_iov, cleanup, opaque);
310
    return nd->vc;
311
}
312

    
313

    
314
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
315
{
316
    memcpy(macaddr, dev->nd->macaddr, 6);
317
}
318

    
319
static int next_block_unit[IF_COUNT];
320

    
321
/* Get a block device.  This should only be used for single-drive devices
322
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
323
   appropriate bus.  */
324
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
325
{
326
    int unit = next_block_unit[type]++;
327
    DriveInfo *dinfo;
328

    
329
    dinfo = drive_get(type, 0, unit);
330
    return dinfo ? dinfo->bdrv : NULL;
331
}
332

    
333
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
334
{
335
    BusState *bus;
336

    
337
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
338
        if (strcmp(name, bus->name) == 0) {
339
            return bus;
340
        }
341
    }
342
    return NULL;
343
}
344

    
345
static BusState *qbus_find_recursive(BusState *bus, const char *name,
346
                                     const BusInfo *info)
347
{
348
    DeviceState *dev;
349
    BusState *child, *ret;
350
    int match = 1;
351

    
352
    if (name && (strcmp(bus->name, name) != 0)) {
353
        match = 0;
354
    }
355
    if (info && (bus->info != info)) {
356
        match = 0;
357
    }
358
    if (match) {
359
        return bus;
360
    }
361

    
362
    QLIST_FOREACH(dev, &bus->children, sibling) {
363
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
364
            ret = qbus_find_recursive(child, name, info);
365
            if (ret) {
366
                return ret;
367
            }
368
        }
369
    }
370
    return NULL;
371
}
372

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

    
379
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
380
                    dev->id ? dev->id : dev->info->name);
381
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
382
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
383
        sep = ", ";
384
    }
385
}
386

    
387
static void qbus_list_dev(BusState *bus, char *dest, int len)
388
{
389
    DeviceState *dev;
390
    const char *sep = " ";
391
    int pos = 0;
392

    
393
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
394
                    bus->name);
395
    QLIST_FOREACH(dev, &bus->children, sibling) {
396
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
397
                        sep, dev->info->name);
398
        if (dev->id)
399
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
400
        sep = ", ";
401
    }
402
}
403

    
404
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
405
{
406
    BusState *child;
407

    
408
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
409
        if (strcmp(child->name, elem) == 0) {
410
            return child;
411
        }
412
    }
413
    return NULL;
414
}
415

    
416
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
417
{
418
    DeviceState *dev;
419

    
420
    /*
421
     * try to match in order:
422
     *   (1) instance id, if present
423
     *   (2) driver name
424
     *   (3) driver alias, if present
425
     */
426
    QLIST_FOREACH(dev, &bus->children, sibling) {
427
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
428
            return dev;
429
        }
430
    }
431
    QLIST_FOREACH(dev, &bus->children, sibling) {
432
        if (strcmp(dev->info->name, elem) == 0) {
433
            return dev;
434
        }
435
    }
436
    QLIST_FOREACH(dev, &bus->children, sibling) {
437
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
438
            return dev;
439
        }
440
    }
441
    return NULL;
442
}
443

    
444
static BusState *qbus_find(const char *path)
445
{
446
    DeviceState *dev;
447
    BusState *bus;
448
    char elem[128], msg[256];
449
    int pos, len;
450

    
451
    /* find start element */
452
    if (path[0] == '/') {
453
        bus = main_system_bus;
454
        pos = 0;
455
    } else {
456
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
457
            qemu_error("path parse error (\"%s\")\n", path);
458
            return NULL;
459
        }
460
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
461
        if (!bus) {
462
            qemu_error("bus \"%s\" not found\n", elem);
463
            return NULL;
464
        }
465
        pos = len;
466
    }
467

    
468
    for (;;) {
469
        if (path[pos] == '\0') {
470
            /* we are done */
471
            return bus;
472
        }
473

    
474
        /* find device */
475
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
476
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
477
            return NULL;
478
        }
479
        pos += len;
480
        dev = qbus_find_dev(bus, elem);
481
        if (!dev) {
482
            qbus_list_dev(bus, msg, sizeof(msg));
483
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
484
            return NULL;
485
        }
486
        if (path[pos] == '\0') {
487
            /* last specified element is a device.  If it has exactly
488
             * one child bus accept it nevertheless */
489
            switch (dev->num_child_bus) {
490
            case 0:
491
                qemu_error("device has no child bus (%s)\n", path);
492
                return NULL;
493
            case 1:
494
                return QLIST_FIRST(&dev->child_bus);
495
            default:
496
                qbus_list_bus(dev, msg, sizeof(msg));
497
                qemu_error("device has multiple child busses (%s)\n%s\n",
498
                           path, msg);
499
                return NULL;
500
            }
501
        }
502

    
503
        /* find bus */
504
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
505
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
506
            return NULL;
507
        }
508
        pos += len;
509
        bus = qbus_find_bus(dev, elem);
510
        if (!bus) {
511
            qbus_list_bus(dev, msg, sizeof(msg));
512
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
513
            return NULL;
514
        }
515
    }
516
}
517

    
518
void qbus_create_inplace(BusState *bus, BusInfo *info,
519
                         DeviceState *parent, const char *name)
520
{
521
    char *buf;
522
    int i,len;
523

    
524
    bus->info = info;
525
    bus->parent = parent;
526

    
527
    if (name) {
528
        /* use supplied name */
529
        bus->name = qemu_strdup(name);
530
    } else if (parent && parent->id) {
531
        /* parent device has id -> use it for bus name */
532
        len = strlen(parent->id) + 16;
533
        buf = qemu_malloc(len);
534
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
535
        bus->name = buf;
536
    } else {
537
        /* no id -> use lowercase bus type for bus name */
538
        len = strlen(info->name) + 16;
539
        buf = qemu_malloc(len);
540
        len = snprintf(buf, len, "%s.%d", info->name,
541
                       parent ? parent->num_child_bus : 0);
542
        for (i = 0; i < len; i++)
543
            buf[i] = qemu_tolower(buf[i]);
544
        bus->name = buf;
545
    }
546

    
547
    QLIST_INIT(&bus->children);
548
    if (parent) {
549
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
550
        parent->num_child_bus++;
551
    }
552

    
553
}
554

    
555
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
556
{
557
    BusState *bus;
558

    
559
    bus = qemu_mallocz(info->size);
560
    bus->qdev_allocated = 1;
561
    qbus_create_inplace(bus, info, parent, name);
562
    return bus;
563
}
564

    
565
void qbus_free(BusState *bus)
566
{
567
    DeviceState *dev;
568

    
569
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
570
        qdev_free(dev);
571
    }
572
    if (bus->parent) {
573
        QLIST_REMOVE(bus, sibling);
574
        bus->parent->num_child_bus--;
575
    }
576
    if (bus->qdev_allocated) {
577
        qemu_free(bus);
578
    }
579
}
580

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

    
584
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
585
                             const char *prefix, int indent)
586
{
587
    char buf[64];
588

    
589
    if (!props)
590
        return;
591
    while (props->name) {
592
        if (props->info->print) {
593
            props->info->print(dev, props, buf, sizeof(buf));
594
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
595
        }
596
        props++;
597
    }
598
}
599

    
600
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
601
{
602
    BusState *child;
603
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
604
                dev->id ? dev->id : "");
605
    indent += 2;
606
    if (dev->num_gpio_in) {
607
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
608
    }
609
    if (dev->num_gpio_out) {
610
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
611
    }
612
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
613
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
614
    if (dev->parent_bus->info->print_dev)
615
        dev->parent_bus->info->print_dev(mon, dev, indent);
616
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
617
        qbus_print(mon, child, indent);
618
    }
619
}
620

    
621
static void qbus_print(Monitor *mon, BusState *bus, int indent)
622
{
623
    struct DeviceState *dev;
624

    
625
    qdev_printf("bus: %s\n", bus->name);
626
    indent += 2;
627
    qdev_printf("type %s\n", bus->info->name);
628
    QLIST_FOREACH(dev, &bus->children, sibling) {
629
        qdev_print(mon, dev, indent);
630
    }
631
}
632
#undef qdev_printf
633

    
634
void do_info_qtree(Monitor *mon)
635
{
636
    if (main_system_bus)
637
        qbus_print(mon, main_system_bus, 0);
638
}
639

    
640
void do_info_qdm(Monitor *mon)
641
{
642
    DeviceInfo *info;
643
    char msg[256];
644

    
645
    for (info = device_info_list; info != NULL; info = info->next) {
646
        qdev_print_devinfo(info, msg, sizeof(msg));
647
        monitor_printf(mon, "%s\n", msg);
648
    }
649
}