qdev.c 42.2 KB
Newer Older
Paul Brook's avatar
Paul Brook committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *  Dynamic device configuration and creation.
 *
 *  Copyright (c) 2009 CodeSourcery
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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/>.
Paul Brook's avatar
Paul Brook committed
18 19 20 21 22 23 24 25 26 27
 */

/* The theory here is that it should be possible to create a machine without
   knowledge of specific devices.  Historically board init routines have
   passed a bunch of arguments to each device, requiring the board know
   exactly which device it is dealing with.  This file provides an abstract
   API for device configuration and initialization.  Devices will generally
   inherit from a particular bus (e.g. PCI or I2C) rather than
   this API directly.  */

Paul Brook's avatar
Paul Brook committed
28
#include "net.h"
Paul Brook's avatar
Paul Brook committed
29 30
#include "qdev.h"
#include "sysemu.h"
31
#include "monitor.h"
Paul Brook's avatar
Paul Brook committed
32

33
static int qdev_hotplug = 0;
34 35
static bool qdev_hot_added = false;
static bool qdev_hot_removed = false;
36

Gerd Hoffmann's avatar
Gerd Hoffmann committed
37
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
Blue Swirl's avatar
Blue Swirl committed
38
static BusState *main_system_bus;
39
static void main_system_bus_create(void);
Paul Brook's avatar
Paul Brook committed
40

41
DeviceInfo *device_info_list;
Paul Brook's avatar
Paul Brook committed
42

43 44 45 46
static BusState *qbus_find_recursive(BusState *bus, const char *name,
                                     const BusInfo *info);
static BusState *qbus_find(const char *path);

Paul Brook's avatar
Paul Brook committed
47
/* Register a new device type.  */
48 49 50
static void qdev_subclass_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
51

52
    dc->info = data;
53 54 55 56
    dc->reset = dc->info->reset;

    /* Poison to try to detect future uses */
    dc->info->reset = NULL;
57 58 59 60

    if (dc->info->class_init) {
        dc->info->class_init(klass, data);
    }
61 62
}

63
static DeviceInfo *qdev_get_info(DeviceState *dev)
64 65 66 67
{
    return DEVICE_GET_CLASS(dev)->info;
}

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
{
    return qdev_get_info(dev)->vmsd;
}

BusInfo *qdev_get_bus_info(DeviceState *dev)
{
    return qdev_get_info(dev)->bus_info;
}

Property *qdev_get_props(DeviceState *dev)
{
    return qdev_get_info(dev)->props;
}

const char *qdev_fw_name(DeviceState *dev)
{
    DeviceInfo *info = qdev_get_info(dev);

    if (info->fw_name) {
        return info->fw_name;
    } else if (info->alias) {
        return info->alias;
    }

    return object_get_typename(OBJECT(dev));
}

96
void qdev_register_subclass(DeviceInfo *info, const char *parent)
Paul Brook's avatar
Paul Brook committed
97
{
98 99
    TypeInfo type_info = {};

100
    assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann's avatar
Gerd Hoffmann committed
101
    assert(!info->next);
Paul Brook's avatar
Paul Brook committed
102

103
    type_info.name = info->name;
104
    type_info.parent = parent;
105
    type_info.instance_size = info->size;
106 107
    type_info.class_init = qdev_subclass_init;
    type_info.class_data = info;
108 109 110

    type_register_static(&type_info);

Gerd Hoffmann's avatar
Gerd Hoffmann committed
111 112
    info->next = device_info_list;
    device_info_list = info;
113 114 115 116 117
}

void qdev_register(DeviceInfo *info)
{
    qdev_register_subclass(info, TYPE_DEVICE);
Paul Brook's avatar
Paul Brook committed
118 119
}

120 121 122 123
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
{
    DeviceInfo *info;

124
    /* first check device names */
125 126 127 128 129 130 131
    for (info = device_info_list; info != NULL; info = info->next) {
        if (bus_info && info->bus_info != bus_info)
            continue;
        if (strcmp(info->name, name) != 0)
            continue;
        return info;
    }
132 133 134 135 136 137 138 139 140 141 142

    /* failing that check the aliases */
    for (info = device_info_list; info != NULL; info = info->next) {
        if (bus_info && info->bus_info != bus_info)
            continue;
        if (!info->alias)
            continue;
        if (strcmp(info->alias, name) != 0)
            continue;
        return info;
    }
143 144 145
    return NULL;
}

Blue Swirl's avatar
Blue Swirl committed
146 147 148 149
bool qdev_exists(const char *name)
{
    return !!qdev_find_info(NULL, name);
}
150

151 152 153
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
                                     Error **errp);

154 155 156
static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
{
    DeviceState *dev;
157
    Property *prop;
158 159

    assert(bus->info == info->bus_info);
160
    dev = DEVICE(object_new(info->name));
161
    dev->parent_bus = bus;
162
    qdev_prop_set_defaults(dev, qdev_get_info(dev)->props);
163 164
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
    qdev_prop_set_globals(dev);
165
    QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
166 167 168
    if (qdev_hotplug) {
        assert(bus->allow_hotplug);
        dev->hotplugged = 1;
169
        qdev_hot_added = true;
170
    }
Jan Kiszka's avatar
Jan Kiszka committed
171
    dev->instance_id_alias = -1;
172
    QTAILQ_INIT(&dev->properties);
173
    dev->state = DEV_STATE_CREATED;
174

175
    for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
176
        qdev_property_add_legacy(dev, prop, NULL);
177
        qdev_property_add_static(dev, prop, NULL);
178 179
    }

180
    for (prop = qdev_get_info(dev)->bus_info->props; prop && prop->name; prop++) {
181
        qdev_property_add_legacy(dev, prop, NULL);
182
        qdev_property_add_static(dev, prop, NULL);
183 184
    }

185 186
    qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);

187 188 189
    return dev;
}

Paul Brook's avatar
Paul Brook committed
190 191 192
/* Create a new device.  This only initializes the device state structure
   and allows properties to be set.  qdev_init should be called to
   initialize the actual device emulation.  */
Paul Brook's avatar
Paul Brook committed
193
DeviceState *qdev_create(BusState *bus, const char *name)
194 195 196 197 198
{
    DeviceState *dev;

    dev = qdev_try_create(bus, name);
    if (!dev) {
199 200 201 202 203 204
        if (bus) {
            hw_error("Unknown device '%s' for bus '%s'\n", name,
                     bus->info->name);
        } else {
            hw_error("Unknown device '%s' for default sysbus\n", name);
        }
205 206 207 208 209 210
    }

    return dev;
}

DeviceState *qdev_try_create(BusState *bus, const char *name)
Paul Brook's avatar
Paul Brook committed
211
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
212
    DeviceInfo *info;
Paul Brook's avatar
Paul Brook committed
213

214
    if (!bus) {
215
        bus = sysbus_get_default();
216 217
    }

218
    info = qdev_find_info(bus->info, name);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
219
    if (!info) {
220
        return NULL;
Paul Brook's avatar
Paul Brook committed
221 222
    }

223
    return qdev_create_from_info(bus, info);
Paul Brook's avatar
Paul Brook committed
224 225
}

226
static void qdev_print_devinfo(DeviceInfo *info)
227
{
228 229
    error_printf("name \"%s\", bus %s",
                 info->name, info->bus_info->name);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
230
    if (info->alias) {
231
        error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
232 233
    }
    if (info->desc) {
234
        error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
235 236
    }
    if (info->no_user) {
237
        error_printf(", no-user");
Gerd Hoffmann's avatar
Gerd Hoffmann committed
238
    }
239
    error_printf("\n");
240 241
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
242
static int set_property(const char *name, const char *value, void *opaque)
243
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
244 245 246 247 248 249 250
    DeviceState *dev = opaque;

    if (strcmp(name, "driver") == 0)
        return 0;
    if (strcmp(name, "bus") == 0)
        return 0;

Mark McLoughlin's avatar
Mark McLoughlin committed
251
    if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
252 253 254 255 256
        return -1;
    }
    return 0;
}

257 258 259 260
int qdev_device_help(QemuOpts *opts)
{
    const char *driver;
    DeviceInfo *info;
261
    Property *prop;
262 263 264 265

    driver = qemu_opt_get(opts, "driver");
    if (driver && !strcmp(driver, "?")) {
        for (info = device_info_list; info != NULL; info = info->next) {
266 267 268
            if (info->no_user) {
                continue;       /* not available, don't show */
            }
269
            qdev_print_devinfo(info);
270 271 272 273
        }
        return 1;
    }

274
    if (!driver || !qemu_opt_get(opts, "?")) {
275 276 277 278 279 280 281 282 283
        return 0;
    }

    info = qdev_find_info(NULL, driver);
    if (!info) {
        return 0;
    }

    for (prop = info->props; prop && prop->name; prop++) {
284 285 286 287 288 289 290 291 292
        /*
         * TODO Properties without a parser are just for dirty hacks.
         * qdev_prop_ptr is the only such PropertyInfo.  It's marked
         * for removal.  This conditional should be removed along with
         * it.
         */
        if (!prop->info->parse) {
            continue;           /* no way to set it, don't show */
        }
293 294
        error_printf("%s.%s=%s\n", info->name, prop->name,
                     prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
295 296 297 298 299
    }
    for (prop = info->bus_info->props; prop && prop->name; prop++) {
        if (!prop->info->parse) {
            continue;           /* no way to set it, don't show */
        }
300 301
        error_printf("%s.%s=%s\n", info->name, prop->name,
                     prop->info->legacy_name ?: prop->info->name);
302 303
    }
    return 1;
304 305
}

306 307 308 309 310 311 312 313 314 315 316 317 318
static DeviceState *qdev_get_peripheral(void)
{
    static DeviceState *dev;

    if (dev == NULL) {
        dev = qdev_create(NULL, "container");
        qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
        qdev_init_nofail(dev);
    }

    return dev;
}

319 320 321 322 323 324 325 326 327 328 329 330 331
static DeviceState *qdev_get_peripheral_anon(void)
{
    static DeviceState *dev;

    if (dev == NULL) {
        dev = qdev_create(NULL, "container");
        qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
        qdev_init_nofail(dev);
    }

    return dev;
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
332 333 334
DeviceState *qdev_device_add(QemuOpts *opts)
{
    const char *driver, *path, *id;
335 336 337 338
    DeviceInfo *info;
    DeviceState *qdev;
    BusState *bus;

Gerd Hoffmann's avatar
Gerd Hoffmann committed
339 340
    driver = qemu_opt_get(opts, "driver");
    if (!driver) {
341
        qerror_report(QERR_MISSING_PARAMETER, "driver");
342 343
        return NULL;
    }
Gerd Hoffmann's avatar
Gerd Hoffmann committed
344 345

    /* find driver */
346
    info = qdev_find_info(NULL, driver);
347
    if (!info || info->no_user) {
348
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
349
        error_printf_unless_qmp("Try with argument '?' for a list.\n");
350 351 352
        return NULL;
    }

Gerd Hoffmann's avatar
Gerd Hoffmann committed
353 354 355
    /* find bus */
    path = qemu_opt_get(opts, "bus");
    if (path != NULL) {
356
        bus = qbus_find(path);
357 358 359 360
        if (!bus) {
            return NULL;
        }
        if (bus->info != info->bus_info) {
361 362
            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
                           driver, bus->info->name);
363 364
            return NULL;
        }
365 366
    } else {
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
367
        if (!bus) {
368 369
            qerror_report(QERR_NO_BUS_FOR_DEVICE,
                           info->name, info->bus_info->name);
370 371
            return NULL;
        }
372
    }
373
    if (qdev_hotplug && !bus->allow_hotplug) {
374
        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
375 376
        return NULL;
    }
377

Gerd Hoffmann's avatar
Gerd Hoffmann committed
378
    /* create device, set properties */
379
    qdev = qdev_create_from_info(bus, info);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
380 381 382
    id = qemu_opts_id(opts);
    if (id) {
        qdev->id = id;
383
        qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
384 385 386 387 388 389 390
    } else {
        static int anon_count;
        gchar *name = g_strdup_printf("device[%d]", anon_count++);
        qdev_property_add_child(qdev_get_peripheral_anon(), name,
                                qdev, NULL);
        g_free(name);
    }        
Gerd Hoffmann's avatar
Gerd Hoffmann committed
391 392 393
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
        qdev_free(qdev);
        return NULL;
394
    }
395
    if (qdev_init(qdev) < 0) {
396
        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
397 398
        return NULL;
    }
399
    qdev->opts = opts;
400 401 402
    return qdev;
}

Paul Brook's avatar
Paul Brook committed
403 404
/* Initialize a device.  Device properties should be set before calling
   this function.  IRQs and MMIO regions should be connected/mapped after
405 406 407
   calling this function.
   On failure, destroy the device and return negative value.
   Return 0 on success.  */
408
int qdev_init(DeviceState *dev)
Paul Brook's avatar
Paul Brook committed
409
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
410 411
    int rc;

Gerd Hoffmann's avatar
Gerd Hoffmann committed
412
    assert(dev->state == DEV_STATE_CREATED);
413
    rc = qdev_get_info(dev)->init(dev, qdev_get_info(dev));
414 415
    if (rc < 0) {
        qdev_free(dev);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
416
        return rc;
417
    }
418 419
    if (qdev_get_info(dev)->vmsd) {
        vmstate_register_with_alias_id(dev, -1, qdev_get_info(dev)->vmsd, dev,
Jan Kiszka's avatar
Jan Kiszka committed
420 421 422
                                       dev->instance_id_alias,
                                       dev->alias_required_for_version);
    }
Gerd Hoffmann's avatar
Gerd Hoffmann committed
423
    dev->state = DEV_STATE_INITIALIZED;
424 425
    if (dev->hotplugged) {
        device_reset(dev);
Jan Kiszka's avatar
Jan Kiszka committed
426
    }
Gerd Hoffmann's avatar
Gerd Hoffmann committed
427
    return 0;
Paul Brook's avatar
Paul Brook committed
428 429
}

Jan Kiszka's avatar
Jan Kiszka committed
430 431 432 433 434 435 436 437
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
                                 int required_for_version)
{
    assert(dev->state == DEV_STATE_CREATED);
    dev->instance_id_alias = alias_id;
    dev->alias_required_for_version = required_for_version;
}

438 439 440
int qdev_unplug(DeviceState *dev)
{
    if (!dev->parent_bus->allow_hotplug) {
441
        qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
442 443
        return -1;
    }
444
    assert(qdev_get_info(dev)->unplug != NULL);
445

446 447
    qdev_hot_removed = true;

448
    return qdev_get_info(dev)->unplug(dev);
449 450
}

451 452
static int qdev_reset_one(DeviceState *dev, void *opaque)
{
453
    device_reset(dev);
454 455 456 457 458 459

    return 0;
}

BusState *sysbus_get_default(void)
{
460
    if (!main_system_bus) {
461
        main_system_bus_create();
462
    }
463 464 465
    return main_system_bus;
}

466 467 468 469 470 471 472 473
static int qbus_reset_one(BusState *bus, void *opaque)
{
    if (bus->info->reset) {
        return bus->info->reset(bus);
    }
    return 0;
}

474 475 476 477 478
void qdev_reset_all(DeviceState *dev)
{
    qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
}

479 480 481
void qbus_reset_all_fn(void *opaque)
{
    BusState *bus = opaque;
482
    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
483 484
}

485 486 487 488 489 490 491 492
/* can be used as ->unplug() callback for the simple cases */
int qdev_simple_unplug_cb(DeviceState *dev)
{
    /* just zap it */
    qdev_free(dev);
    return 0;
}

493 494

/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbruster's avatar
Markus Armbruster committed
495 496 497 498 499 500 501 502
   returning an error value.  This is okay during machine creation.
   Don't use for hotplug, because there callers need to recover from
   failure.  Exception: if you know the device's init() callback can't
   fail, then qdev_init_nofail() can't fail either, and is therefore
   usable even then.  But relying on the device implementation that
   way is somewhat unclean, and best avoided.  */
void qdev_init_nofail(DeviceState *dev)
{
503
    DeviceInfo *info = qdev_get_info(dev);
Markus Armbruster's avatar
Markus Armbruster committed
504

505
    if (qdev_init(dev) < 0) {
506
        error_report("Initialization of device %s failed", info->name);
507 508
        exit(1);
    }
Markus Armbruster's avatar
Markus Armbruster committed
509 510
}

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
static void qdev_property_del_all(DeviceState *dev)
{
    while (!QTAILQ_EMPTY(&dev->properties)) {
        DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);

        QTAILQ_REMOVE(&dev->properties, prop, node);

        if (prop->release) {
            prop->release(dev, prop->name, prop->opaque);
        }

        g_free(prop->name);
        g_free(prop->type);
        g_free(prop);
    }
}

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
{
    DeviceProperty *prop;

    QTAILQ_FOREACH(prop, &dev->properties, node) {
        if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
            break;
        }
    }

    g_assert(prop != NULL);

    QTAILQ_REMOVE(&dev->properties, prop, node);

    if (prop->release) {
        prop->release(dev, prop->name, prop->opaque);
    }

    g_free(prop->name);
    g_free(prop->type);
    g_free(prop);
}

Paul Brook's avatar
Paul Brook committed
551 552 553
/* Unlink device from bus and free the structure.  */
void qdev_free(DeviceState *dev)
{
Gerd Hoffmann's avatar
Gerd Hoffmann committed
554
    BusState *bus;
555
    Property *prop;
Gerd Hoffmann's avatar
Gerd Hoffmann committed
556

557 558
    qdev_property_del_all(dev);

Gerd Hoffmann's avatar
Gerd Hoffmann committed
559 560 561 562 563
    if (dev->state == DEV_STATE_INITIALIZED) {
        while (dev->num_child_bus) {
            bus = QLIST_FIRST(&dev->child_bus);
            qbus_free(bus);
        }
564 565 566 567
        if (qdev_get_info(dev)->vmsd)
            vmstate_unregister(dev, qdev_get_info(dev)->vmsd, dev);
        if (qdev_get_info(dev)->exit)
            qdev_get_info(dev)->exit(dev);
568 569
        if (dev->opts)
            qemu_opts_del(dev->opts);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
570
    }
571
    QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
572
    for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
573 574 575 576
        if (prop->info->free) {
            prop->info->free(dev, prop);
        }
    }
577 578 579 580 581 582
    if (dev->parent) {
        qdev_property_del_child(dev->parent, dev, NULL);
    }
    if (dev->ref != 0) {
        qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
    }
583
    object_delete(OBJECT(dev));
Paul Brook's avatar
Paul Brook committed
584 585
}

586 587 588 589 590 591 592 593 594
void qdev_machine_creation_done(void)
{
    /*
     * ok, initial machine setup is done, starting from now we can
     * only create hotpluggable devices
     */
    qdev_hotplug = 1;
}

595 596 597 598 599
bool qdev_machine_modified(void)
{
    return qdev_hot_added || qdev_hot_removed;
}

Paul Brook's avatar
Paul Brook committed
600 601 602 603
/* Get a character (serial) device interface.  */
CharDriverState *qdev_init_chardev(DeviceState *dev)
{
    static int next_serial;
604 605 606

    /* FIXME: This function needs to go away: use chardev properties!  */
    return serial_hds[next_serial++];
Paul Brook's avatar
Paul Brook committed
607 608
}

Paul Brook's avatar
Paul Brook committed
609
BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brook's avatar
Paul Brook committed
610
{
Paul Brook's avatar
Paul Brook committed
611
    return dev->parent_bus;
Paul Brook's avatar
Paul Brook committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
}

void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
{
    assert(dev->num_gpio_in == 0);
    dev->num_gpio_in = n;
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
}

void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
{
    assert(dev->num_gpio_out == 0);
    dev->num_gpio_out = n;
    dev->gpio_out = pins;
}

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

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

640 641
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
{
642
    qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
643 644 645 646
    if (nd->vlan)
        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
    if (nd->netdev)
        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
647
    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
648 649 650
        qdev_prop_exists(dev, "vectors")) {
        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
    }
651
    nd->instantiated = 1;
652 653
}

Paul Brook's avatar
Paul Brook committed
654
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook's avatar
Paul Brook committed
655
{
Paul Brook's avatar
Paul Brook committed
656
    BusState *bus;
Paul Brook's avatar
Paul Brook committed
657

Blue Swirl's avatar
Blue Swirl committed
658
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook's avatar
Paul Brook committed
659
        if (strcmp(name, bus->name) == 0) {
Paul Brook's avatar
Paul Brook committed
660
            return bus;
Paul Brook's avatar
Paul Brook committed
661 662 663 664 665
        }
    }
    return NULL;
}

666 667 668 669 670 671 672 673 674 675 676 677 678
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
                       qbus_walkerfn *busfn, void *opaque)
{
    DeviceState *dev;
    int err;

    if (busfn) {
        err = busfn(bus, opaque);
        if (err) {
            return err;
        }
    }

679
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
        err = qdev_walk_children(dev, devfn, busfn, opaque);
        if (err < 0) {
            return err;
        }
    }

    return 0;
}

int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                       qbus_walkerfn *busfn, void *opaque)
{
    BusState *bus;
    int err;

    if (devfn) {
        err = devfn(dev, opaque);
        if (err) {
            return err;
        }
    }

    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
        err = qbus_walk_children(bus, devfn, busfn, opaque);
        if (err < 0) {
            return err;
        }
    }

    return 0;
}

712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
static BusState *qbus_find_recursive(BusState *bus, const char *name,
                                     const BusInfo *info)
{
    DeviceState *dev;
    BusState *child, *ret;
    int match = 1;

    if (name && (strcmp(bus->name, name) != 0)) {
        match = 0;
    }
    if (info && (bus->info != info)) {
        match = 0;
    }
    if (match) {
        return bus;
    }

729
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl's avatar
Blue Swirl committed
730
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
731 732 733 734 735 736 737 738 739
            ret = qbus_find_recursive(child, name, info);
            if (ret) {
                return ret;
            }
        }
    }
    return NULL;
}

740
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
741 742 743 744
{
    DeviceState *dev, *ret;
    BusState *child;

745
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
746 747 748 749 750 751 752 753 754 755 756 757
        if (dev->id && strcmp(dev->id, id) == 0)
            return dev;
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
            ret = qdev_find_recursive(child, id);
            if (ret) {
                return ret;
            }
        }
    }
    return NULL;
}

758
static void qbus_list_bus(DeviceState *dev)
759 760 761 762
{
    BusState *child;
    const char *sep = " ";

763
    error_printf("child busses at \"%s\":",
764
                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl's avatar
Blue Swirl committed
765
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
766
        error_printf("%s\"%s\"", sep, child->name);
767 768
        sep = ", ";
    }
769
    error_printf("\n");
770 771
}

772
static void qbus_list_dev(BusState *bus)
773 774 775 776
{
    DeviceState *dev;
    const char *sep = " ";

777
    error_printf("devices at \"%s\":", bus->name);
778
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
779
        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
780
        if (dev->id)
781
            error_printf("/\"%s\"", dev->id);
782 783
        sep = ", ";
    }
784
    error_printf("\n");
785 786 787 788 789 790
}

static BusState *qbus_find_bus(DeviceState *dev, char *elem)
{
    BusState *child;

Blue Swirl's avatar
Blue Swirl committed
791
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
        if (strcmp(child->name, elem) == 0) {
            return child;
        }
    }
    return NULL;
}

static DeviceState *qbus_find_dev(BusState *bus, char *elem)
{
    DeviceState *dev;

    /*
     * try to match in order:
     *   (1) instance id, if present
     *   (2) driver name
     *   (3) driver alias, if present
     */
809
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
810 811 812 813
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
            return dev;
        }
    }
814
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
815
        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
816 817 818
            return dev;
        }
    }
819
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
820
        if (qdev_get_info(dev)->alias && strcmp(qdev_get_info(dev)->alias, elem) == 0) {
821 822 823 824 825 826 827 828 829 830
            return dev;
        }
    }
    return NULL;
}

static BusState *qbus_find(const char *path)
{
    DeviceState *dev;
    BusState *bus;
831
    char elem[128];
832 833 834 835 836 837 838 839
    int pos, len;

    /* find start element */
    if (path[0] == '/') {
        bus = main_system_bus;
        pos = 0;
    } else {
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
840 841
            assert(!path[0]);
            elem[0] = len = 0;
842 843 844
        }
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
        if (!bus) {
845
            qerror_report(QERR_BUS_NOT_FOUND, elem);
846 847 848 849 850 851
            return NULL;
        }
        pos = len;
    }

    for (;;) {
852 853 854 855
        assert(path[pos] == '/' || !path[pos]);
        while (path[pos] == '/') {
            pos++;
        }
856 857 858 859 860
        if (path[pos] == '\0') {
            return bus;
        }

        /* find device */
861 862 863
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
            assert(0);
            elem[0] = len = 0;
864 865 866 867
        }
        pos += len;
        dev = qbus_find_dev(bus, elem);
        if (!dev) {
868
            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
869 870 871
            if (!monitor_cur_is_qmp()) {
                qbus_list_dev(bus);
            }
872 873
            return NULL;
        }
874 875 876 877 878

        assert(path[pos] == '/' || !path[pos]);
        while (path[pos] == '/') {
            pos++;
        }
879 880 881 882 883
        if (path[pos] == '\0') {
            /* last specified element is a device.  If it has exactly
             * one child bus accept it nevertheless */
            switch (dev->num_child_bus) {
            case 0:
884
                qerror_report(QERR_DEVICE_NO_BUS, elem);
885 886
                return NULL;
            case 1:
Blue Swirl's avatar
Blue Swirl committed
887
                return QLIST_FIRST(&dev->child_bus);
888
            default:
889
                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
890 891 892
                if (!monitor_cur_is_qmp()) {
                    qbus_list_bus(dev);
                }
893 894 895 896 897
                return NULL;
            }
        }

        /* find bus */
898 899 900
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
            assert(0);
            elem[0] = len = 0;
901 902 903 904
        }
        pos += len;
        bus = qbus_find_bus(dev, elem);
        if (!bus) {
905
            qerror_report(QERR_BUS_NOT_FOUND, elem);
906 907 908
            if (!monitor_cur_is_qmp()) {
                qbus_list_bus(dev);
            }
909 910 911 912 913
            return NULL;
        }
    }
}

914 915
void qbus_create_inplace(BusState *bus, BusInfo *info,
                         DeviceState *parent, const char *name)
Paul Brook's avatar
Paul Brook committed
916
{
917 918
    char *buf;
    int i,len;
Paul Brook's avatar
Paul Brook committed
919

920
    bus->info = info;
Paul Brook's avatar
Paul Brook committed
921
    bus->parent = parent;
922 923 924

    if (name) {
        /* use supplied name */
925
        bus->name = g_strdup(name);
926 927 928
    } else if (parent && parent->id) {
        /* parent device has id -> use it for bus name */
        len = strlen(parent->id) + 16;
929
        buf = g_malloc(len);
930 931 932 933 934
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
        bus->name = buf;
    } else {
        /* no id -> use lowercase bus type for bus name */
        len = strlen(info->name) + 16;
935
        buf = g_malloc(len);
936 937 938
        len = snprintf(buf, len, "%s.%d", info->name,
                       parent ? parent->num_child_bus : 0);
        for (i = 0; i < len; i++)
Christoph Egger's avatar
Christoph Egger committed
939
            buf[i] = qemu_tolower(buf[i]);
940 941 942
        bus->name = buf;
    }

943
    QTAILQ_INIT(&bus->children);
Paul Brook's avatar
Paul Brook committed
944
    if (parent) {
Blue Swirl's avatar
Blue Swirl committed
945
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
946
        parent->num_child_bus++;
947 948 949 950
    } else if (bus != main_system_bus) {
        /* TODO: once all bus devices are qdevified,
           only reset handler for main_system_bus should be registered here. */
        qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook's avatar
Paul Brook committed
951
    }
952 953 954 955 956 957
}

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

958
    bus = g_malloc0(info->size);
959 960
    bus->qdev_allocated = 1;
    qbus_create_inplace(bus, info, parent, name);
Paul Brook's avatar
Paul Brook committed
961 962
    return bus;
}
963

964 965 966 967
static void main_system_bus_create(void)
{
    /* assign main_system_bus before qbus_create_inplace()
     * in order to make "if (bus != main_system_bus)" work */
968
    main_system_bus = g_malloc0(system_bus_info.size);
969 970 971 972 973
    main_system_bus->qdev_allocated = 1;
    qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
                        "main-system-bus");
}

Gerd Hoffmann's avatar
Gerd Hoffmann committed
974 975 976 977
void qbus_free(BusState *bus)
{
    DeviceState *dev;

978
    while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann's avatar
Gerd Hoffmann committed
979 980 981 982 983
        qdev_free(dev);
    }
    if (bus->parent) {
        QLIST_REMOVE(bus, sibling);
        bus->parent->num_child_bus--;
984 985 986
    } else {
        assert(bus != main_system_bus); /* main_system_bus is never freed */
        qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
987
    }
988
    g_free((void*)bus->name);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
989
    if (bus->qdev_allocated) {
990
        g_free(bus);
Gerd Hoffmann's avatar
Gerd Hoffmann committed
991 992 993
    }
}

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

Gerd Hoffmann's avatar