Statistics
| Branch: | Revision:

root / hw / qdev.c @ 959f733a

History | View | Annotate | Download (16.7 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
    LIST_INSERT_HEAD(&bus->children, dev, sibling);
105
    return dev;
106
}
107

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

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

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

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

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

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

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

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

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

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

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

    
219
    rc = dev->info->init(dev, dev->info);
220
    if (rc < 0)
221
        return rc;
222
    if (dev->info->reset)
223
        qemu_register_reset(dev->info->reset, dev);
224
    return 0;
225
}
226

    
227
/* Unlink device from bus and free the structure.  */
228
void qdev_free(DeviceState *dev)
229
{
230
    if (dev->info->reset)
231
        qemu_unregister_reset(dev->info->reset, dev);
232
    LIST_REMOVE(dev, sibling);
233
    qemu_free(dev);
234
}
235

    
236
/* Get a character (serial) device interface.  */
237
CharDriverState *qdev_init_chardev(DeviceState *dev)
238
{
239
    static int next_serial;
240
    static int next_virtconsole;
241
    /* FIXME: This is a nasty hack that needs to go away.  */
242
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
243
        return virtcon_hds[next_virtconsole++];
244
    } else {
245
        return serial_hds[next_serial++];
246
    }
247
}
248

    
249
BusState *qdev_get_parent_bus(DeviceState *dev)
250
{
251
    return dev->parent_bus;
252
}
253

    
254
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
255
{
256
    assert(dev->num_gpio_in == 0);
257
    dev->num_gpio_in = n;
258
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
259
}
260

    
261
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
262
{
263
    assert(dev->num_gpio_out == 0);
264
    dev->num_gpio_out = n;
265
    dev->gpio_out = pins;
266
}
267

    
268
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
269
{
270
    assert(n >= 0 && n < dev->num_gpio_in);
271
    return dev->gpio_in[n];
272
}
273

    
274
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
275
{
276
    assert(n >= 0 && n < dev->num_gpio_out);
277
    dev->gpio_out[n] = pin;
278
}
279

    
280
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
281
                                      NetCanReceive *can_receive,
282
                                      NetReceive *receive,
283
                                      NetReceiveIOV *receive_iov,
284
                                      NetCleanup *cleanup,
285
                                      void *opaque)
286
{
287
    NICInfo *nd = dev->nd;
288
    assert(nd);
289
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
290
                                  receive, receive_iov, cleanup, opaque);
291
    return nd->vc;
292
}
293

    
294

    
295
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
296
{
297
    memcpy(macaddr, dev->nd->macaddr, 6);
298
}
299

    
300
static int next_block_unit[IF_COUNT];
301

    
302
/* Get a block device.  This should only be used for single-drive devices
303
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
304
   appropriate bus.  */
305
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
306
{
307
    int unit = next_block_unit[type]++;
308
    DriveInfo *dinfo;
309

    
310
    dinfo = drive_get(type, 0, unit);
311
    return dinfo ? dinfo->bdrv : NULL;
312
}
313

    
314
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
315
{
316
    BusState *bus;
317

    
318
    LIST_FOREACH(bus, &dev->child_bus, sibling) {
319
        if (strcmp(name, bus->name) == 0) {
320
            return bus;
321
        }
322
    }
323
    return NULL;
324
}
325

    
326
static BusState *qbus_find_recursive(BusState *bus, const char *name,
327
                                     const BusInfo *info)
328
{
329
    DeviceState *dev;
330
    BusState *child, *ret;
331
    int match = 1;
332

    
333
    if (name && (strcmp(bus->name, name) != 0)) {
334
        match = 0;
335
    }
336
    if (info && (bus->info != info)) {
337
        match = 0;
338
    }
339
    if (match) {
340
        return bus;
341
    }
342

    
343
    LIST_FOREACH(dev, &bus->children, sibling) {
344
        LIST_FOREACH(child, &dev->child_bus, sibling) {
345
            ret = qbus_find_recursive(child, name, info);
346
            if (ret) {
347
                return ret;
348
            }
349
        }
350
    }
351
    return NULL;
352
}
353

    
354
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
355
{
356
    BusState *child;
357
    const char *sep = " ";
358
    int pos = 0;
359

    
360
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
361
                    dev->id ? dev->id : dev->info->name);
362
    LIST_FOREACH(child, &dev->child_bus, sibling) {
363
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
364
        sep = ", ";
365
    }
366
}
367

    
368
static void qbus_list_dev(BusState *bus, char *dest, int len)
369
{
370
    DeviceState *dev;
371
    const char *sep = " ";
372
    int pos = 0;
373

    
374
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
375
                    bus->name);
376
    LIST_FOREACH(dev, &bus->children, sibling) {
377
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
378
                        sep, dev->info->name);
379
        if (dev->id)
380
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
381
        sep = ", ";
382
    }
383
}
384

    
385
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
386
{
387
    BusState *child;
388

    
389
    LIST_FOREACH(child, &dev->child_bus, sibling) {
390
        if (strcmp(child->name, elem) == 0) {
391
            return child;
392
        }
393
    }
394
    return NULL;
395
}
396

    
397
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
398
{
399
    DeviceState *dev;
400

    
401
    /*
402
     * try to match in order:
403
     *   (1) instance id, if present
404
     *   (2) driver name
405
     *   (3) driver alias, if present
406
     */
407
    LIST_FOREACH(dev, &bus->children, sibling) {
408
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
409
            return dev;
410
        }
411
    }
412
    LIST_FOREACH(dev, &bus->children, sibling) {
413
        if (strcmp(dev->info->name, elem) == 0) {
414
            return dev;
415
        }
416
    }
417
    LIST_FOREACH(dev, &bus->children, sibling) {
418
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
419
            return dev;
420
        }
421
    }
422
    return NULL;
423
}
424

    
425
static BusState *qbus_find(const char *path)
426
{
427
    DeviceState *dev;
428
    BusState *bus;
429
    char elem[128], msg[256];
430
    int pos, len;
431

    
432
    /* find start element */
433
    if (path[0] == '/') {
434
        bus = main_system_bus;
435
        pos = 0;
436
    } else {
437
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
438
            qemu_error("path parse error (\"%s\")\n", path);
439
            return NULL;
440
        }
441
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
442
        if (!bus) {
443
            qemu_error("bus \"%s\" not found\n", elem);
444
            return NULL;
445
        }
446
        pos = len;
447
    }
448

    
449
    for (;;) {
450
        if (path[pos] == '\0') {
451
            /* we are done */
452
            return bus;
453
        }
454

    
455
        /* find device */
456
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
457
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
458
            return NULL;
459
        }
460
        pos += len;
461
        dev = qbus_find_dev(bus, elem);
462
        if (!dev) {
463
            qbus_list_dev(bus, msg, sizeof(msg));
464
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
465
            return NULL;
466
        }
467
        if (path[pos] == '\0') {
468
            /* last specified element is a device.  If it has exactly
469
             * one child bus accept it nevertheless */
470
            switch (dev->num_child_bus) {
471
            case 0:
472
                qemu_error("device has no child bus (%s)\n", path);
473
                return NULL;
474
            case 1:
475
                return LIST_FIRST(&dev->child_bus);
476
            default:
477
                qbus_list_bus(dev, msg, sizeof(msg));
478
                qemu_error("device has multiple child busses (%s)\n%s\n",
479
                           path, msg);
480
                return NULL;
481
            }
482
        }
483

    
484
        /* find bus */
485
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
486
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
487
            return NULL;
488
        }
489
        pos += len;
490
        bus = qbus_find_bus(dev, elem);
491
        if (!bus) {
492
            qbus_list_bus(dev, msg, sizeof(msg));
493
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
494
            return NULL;
495
        }
496
    }
497
}
498

    
499
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
500
{
501
    BusState *bus;
502
    char *buf;
503
    int i,len;
504

    
505
    bus = qemu_mallocz(info->size);
506
    bus->info = info;
507
    bus->parent = parent;
508

    
509
    if (name) {
510
        /* use supplied name */
511
        bus->name = qemu_strdup(name);
512
    } else if (parent && parent->id) {
513
        /* parent device has id -> use it for bus name */
514
        len = strlen(parent->id) + 16;
515
        buf = qemu_malloc(len);
516
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
517
        bus->name = buf;
518
    } else {
519
        /* no id -> use lowercase bus type for bus name */
520
        len = strlen(info->name) + 16;
521
        buf = qemu_malloc(len);
522
        len = snprintf(buf, len, "%s.%d", info->name,
523
                       parent ? parent->num_child_bus : 0);
524
        for (i = 0; i < len; i++)
525
            buf[i] = qemu_tolower(buf[i]);
526
        bus->name = buf;
527
    }
528

    
529
    LIST_INIT(&bus->children);
530
    if (parent) {
531
        LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
532
        parent->num_child_bus++;
533
    }
534
    return bus;
535
}
536

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

    
540
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
541
                             const char *prefix, int indent)
542
{
543
    char buf[64];
544

    
545
    if (!props)
546
        return;
547
    while (props->name) {
548
        if (props->info->print) {
549
            props->info->print(dev, props, buf, sizeof(buf));
550
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
551
        }
552
        props++;
553
    }
554
}
555

    
556
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
557
{
558
    BusState *child;
559
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
560
                dev->id ? dev->id : "");
561
    indent += 2;
562
    if (dev->num_gpio_in) {
563
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
564
    }
565
    if (dev->num_gpio_out) {
566
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
567
    }
568
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
569
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
570
    if (dev->parent_bus->info->print_dev)
571
        dev->parent_bus->info->print_dev(mon, dev, indent);
572
    LIST_FOREACH(child, &dev->child_bus, sibling) {
573
        qbus_print(mon, child, indent);
574
    }
575
}
576

    
577
static void qbus_print(Monitor *mon, BusState *bus, int indent)
578
{
579
    struct DeviceState *dev;
580

    
581
    qdev_printf("bus: %s\n", bus->name);
582
    indent += 2;
583
    qdev_printf("type %s\n", bus->info->name);
584
    LIST_FOREACH(dev, &bus->children, sibling) {
585
        qdev_print(mon, dev, indent);
586
    }
587
}
588
#undef qdev_printf
589

    
590
void do_info_qtree(Monitor *mon)
591
{
592
    if (main_system_bus)
593
        qbus_print(mon, main_system_bus, 0);
594
}
595

    
596
void do_info_qdm(Monitor *mon)
597
{
598
    DeviceInfo *info;
599
    char msg[256];
600

    
601
    for (info = device_info_list; info != NULL; info = info->next) {
602
        qdev_print_devinfo(info, msg, sizeof(msg));
603
        monitor_printf(mon, "%s\n", msg);
604
    }
605
}