]> git.proxmox.com Git - mirror_qemu.git/blame - hw/qdev.c
qbus: Make child devices links
[mirror_qemu.git] / hw / qdev.c
CommitLineData
aae9460e
PB
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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
aae9460e
PB
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
9d07d757 28#include "net.h"
aae9460e
PB
29#include "qdev.h"
30#include "sysemu.h"
56f9107e 31#include "error.h"
aae9460e 32
ee46d8a5 33int qdev_hotplug = 0;
0ac8ef71
AW
34static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
3418bd25 36
aae9460e 37/* Register a new device type. */
4be9f0d1
AL
38const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
39{
6e008585
AL
40 DeviceClass *dc = DEVICE_GET_CLASS(dev);
41 return dc->vmsd;
4be9f0d1
AL
42}
43
4be9f0d1
AL
44const char *qdev_fw_name(DeviceState *dev)
45{
6e008585 46 DeviceClass *dc = DEVICE_GET_CLASS(dev);
4be9f0d1 47
6e008585
AL
48 if (dc->fw_name) {
49 return dc->fw_name;
4be9f0d1
AL
50 }
51
52 return object_get_typename(OBJECT(dev));
53}
54
a369da5f
BS
55bool qdev_exists(const char *name)
56{
212ad111 57 return !!object_class_by_name(name);
a369da5f 58}
40021f08 59
ca2cc788
PB
60static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
61 Error **errp);
62
0866aca1 63static void bus_remove_child(BusState *bus, DeviceState *child)
0c17542d 64{
0866aca1
AL
65 BusChild *kid;
66
67 QTAILQ_FOREACH(kid, &bus->children, sibling) {
68 if (kid->child == child) {
69 char name[32];
70
71 snprintf(name, sizeof(name), "child[%d]", kid->index);
72 QTAILQ_REMOVE(&bus->children, kid, sibling);
73 object_property_del(OBJECT(bus), name, NULL);
74 g_free(kid);
75 return;
76 }
77 }
78}
79
80static void bus_add_child(BusState *bus, DeviceState *child)
81{
82 char name[32];
83 BusChild *kid = g_malloc0(sizeof(*kid));
84
0c17542d
MA
85 if (qdev_hotplug) {
86 assert(bus->allow_hotplug);
0c17542d 87 }
a5296ca9 88
0866aca1
AL
89 kid->index = bus->max_index++;
90 kid->child = child;
91
92 QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
93
94 snprintf(name, sizeof(name), "child[%d]", kid->index);
95 object_property_add_link(OBJECT(bus), name,
96 object_get_typename(OBJECT(child)),
97 (Object **)&kid->child,
98 NULL);
99}
100
101void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
102{
9fbe6127 103 dev->parent_bus = bus;
0866aca1 104 bus_add_child(bus, dev);
0c17542d
MA
105}
106
aae9460e
PB
107/* Create a new device. This only initializes the device state structure
108 and allows properties to be set. qdev_init should be called to
109 initialize the actual device emulation. */
02e2da45 110DeviceState *qdev_create(BusState *bus, const char *name)
0bcdeda7
BS
111{
112 DeviceState *dev;
113
114 dev = qdev_try_create(bus, name);
115 if (!dev) {
e92714c7
PM
116 if (bus) {
117 hw_error("Unknown device '%s' for bus '%s'\n", name,
0d936928 118 object_get_typename(OBJECT(bus)));
e92714c7
PM
119 } else {
120 hw_error("Unknown device '%s' for default sysbus\n", name);
121 }
0bcdeda7
BS
122 }
123
124 return dev;
125}
126
da57febf 127DeviceState *qdev_try_create(BusState *bus, const char *type)
aae9460e 128{
9fbe6127
AL
129 DeviceState *dev;
130
da57febf 131 if (object_class_by_name(type) == NULL) {
4ed658ca
AF
132 return NULL;
133 }
da57febf 134 dev = DEVICE(object_new(type));
9fbe6127
AL
135 if (!dev) {
136 return NULL;
137 }
138
10c4c98a 139 if (!bus) {
68694897 140 bus = sysbus_get_default();
10c4c98a
GH
141 }
142
9fbe6127 143 qdev_set_parent_bus(dev, bus);
9fbe6127
AL
144
145 return dev;
aae9460e
PB
146}
147
148/* Initialize a device. Device properties should be set before calling
149 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
150 calling this function.
151 On failure, destroy the device and return negative value.
152 Return 0 on success. */
81a322d4 153int qdev_init(DeviceState *dev)
aae9460e 154{
6e008585 155 DeviceClass *dc = DEVICE_GET_CLASS(dev);
959f733a
GH
156 int rc;
157
131ec1bd 158 assert(dev->state == DEV_STATE_CREATED);
6e008585 159
d307af79 160 rc = dc->init(dev);
18cfeb52
MA
161 if (rc < 0) {
162 qdev_free(dev);
959f733a 163 return rc;
18cfeb52 164 }
da57febf
PB
165
166 if (!OBJECT(dev)->parent) {
167 static int unattached_count = 0;
168 gchar *name = g_strdup_printf("device[%d]", unattached_count++);
169
dfe47e70
AF
170 object_property_add_child(container_get(qdev_get_machine(),
171 "/unattached"),
172 name, OBJECT(dev), NULL);
da57febf
PB
173 g_free(name);
174 }
175
6e008585
AL
176 if (qdev_get_vmsd(dev)) {
177 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
4d2ffa08
JK
178 dev->instance_id_alias,
179 dev->alias_required_for_version);
180 }
131ec1bd 181 dev->state = DEV_STATE_INITIALIZED;
94afdadc
AL
182 if (dev->hotplugged) {
183 device_reset(dev);
5ab28c83 184 }
959f733a 185 return 0;
02e2da45
PB
186}
187
4d2ffa08
JK
188void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
189 int required_for_version)
190{
191 assert(dev->state == DEV_STATE_CREATED);
192 dev->instance_id_alias = alias_id;
193 dev->alias_required_for_version = required_for_version;
194}
195
56f9107e 196void qdev_unplug(DeviceState *dev, Error **errp)
3418bd25 197{
6e008585
AL
198 DeviceClass *dc = DEVICE_GET_CLASS(dev);
199
3418bd25 200 if (!dev->parent_bus->allow_hotplug) {
56f9107e
LC
201 error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
202 return;
3418bd25 203 }
6e008585 204 assert(dc->unplug != NULL);
593831de 205
0ac8ef71
AW
206 qdev_hot_removed = true;
207
56f9107e
LC
208 if (dc->unplug(dev) < 0) {
209 error_set(errp, QERR_UNDEFINED_ERROR);
210 return;
211 }
3418bd25
GH
212}
213
ec990eb6
AL
214static int qdev_reset_one(DeviceState *dev, void *opaque)
215{
94afdadc 216 device_reset(dev);
ec990eb6
AL
217
218 return 0;
219}
220
b4694b7c
IY
221static int qbus_reset_one(BusState *bus, void *opaque)
222{
0d936928
AL
223 BusClass *bc = BUS_GET_CLASS(bus);
224 if (bc->reset) {
225 return bc->reset(bus);
b4694b7c
IY
226 }
227 return 0;
228}
229
5af0a04b
IY
230void qdev_reset_all(DeviceState *dev)
231{
232 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
233}
234
80376c3f
IY
235void qbus_reset_all_fn(void *opaque)
236{
237 BusState *bus = opaque;
f530cce3 238 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
80376c3f
IY
239}
240
3418bd25
GH
241/* can be used as ->unplug() callback for the simple cases */
242int qdev_simple_unplug_cb(DeviceState *dev)
243{
244 /* just zap it */
57c9fafe 245 object_unparent(OBJECT(dev));
3418bd25
GH
246 qdev_free(dev);
247 return 0;
248}
249
3b29a101
MT
250
251/* Like qdev_init(), but terminate program via error_report() instead of
e23a1b33
MA
252 returning an error value. This is okay during machine creation.
253 Don't use for hotplug, because there callers need to recover from
254 failure. Exception: if you know the device's init() callback can't
255 fail, then qdev_init_nofail() can't fail either, and is therefore
256 usable even then. But relying on the device implementation that
257 way is somewhat unclean, and best avoided. */
258void qdev_init_nofail(DeviceState *dev)
259{
bd6c9a61 260 if (qdev_init(dev) < 0) {
6e008585
AL
261 error_report("Initialization of device %s failed",
262 object_get_typename(OBJECT(dev)));
bd6c9a61
MA
263 exit(1);
264 }
e23a1b33
MA
265}
266
02e2da45
PB
267/* Unlink device from bus and free the structure. */
268void qdev_free(DeviceState *dev)
269{
32fea402 270 object_delete(OBJECT(dev));
aae9460e
PB
271}
272
3418bd25
GH
273void qdev_machine_creation_done(void)
274{
275 /*
276 * ok, initial machine setup is done, starting from now we can
277 * only create hotpluggable devices
278 */
279 qdev_hotplug = 1;
280}
281
0ac8ef71
AW
282bool qdev_machine_modified(void)
283{
284 return qdev_hot_added || qdev_hot_removed;
285}
286
02e2da45 287BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 288{
02e2da45 289 return dev->parent_bus;
aae9460e
PB
290}
291
aae9460e
PB
292void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
293{
294 assert(dev->num_gpio_in == 0);
295 dev->num_gpio_in = n;
296 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
297}
298
299void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
300{
301 assert(dev->num_gpio_out == 0);
302 dev->num_gpio_out = n;
303 dev->gpio_out = pins;
304}
305
306qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
307{
308 assert(n >= 0 && n < dev->num_gpio_in);
309 return dev->gpio_in[n];
310}
311
312void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
313{
314 assert(n >= 0 && n < dev->num_gpio_out);
315 dev->gpio_out[n] = pin;
316}
317
ed16ab5a
GH
318void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
319{
6eed1856 320 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
ed16ab5a
GH
321 if (nd->vlan)
322 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
323 if (nd->netdev)
324 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
75422b0d 325 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
97b15621
GH
326 qdev_prop_exists(dev, "vectors")) {
327 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
328 }
48e2faf2 329 nd->instantiated = 1;
ed16ab5a
GH
330}
331
02e2da45 332BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 333{
02e2da45 334 BusState *bus;
4d6ae674 335
72cf2d4f 336 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 337 if (strcmp(name, bus->name) == 0) {
02e2da45 338 return bus;
4d6ae674
PB
339 }
340 }
341 return NULL;
342}
343
81699d8a
AL
344int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
345 qbus_walkerfn *busfn, void *opaque)
346{
0866aca1 347 BusChild *kid;
81699d8a
AL
348 int err;
349
350 if (busfn) {
351 err = busfn(bus, opaque);
352 if (err) {
353 return err;
354 }
355 }
356
0866aca1
AL
357 QTAILQ_FOREACH(kid, &bus->children, sibling) {
358 err = qdev_walk_children(kid->child, devfn, busfn, opaque);
81699d8a
AL
359 if (err < 0) {
360 return err;
361 }
362 }
363
364 return 0;
365}
366
367int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
368 qbus_walkerfn *busfn, void *opaque)
369{
370 BusState *bus;
371 int err;
372
373 if (devfn) {
374 err = devfn(dev, opaque);
375 if (err) {
376 return err;
377 }
378 }
379
380 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
381 err = qbus_walk_children(bus, devfn, busfn, opaque);
382 if (err < 0) {
383 return err;
384 }
385 }
386
387 return 0;
388}
389
a2ee6b4f 390DeviceState *qdev_find_recursive(BusState *bus, const char *id)
3418bd25 391{
0866aca1
AL
392 BusChild *kid;
393 DeviceState *ret;
3418bd25
GH
394 BusState *child;
395
0866aca1
AL
396 QTAILQ_FOREACH(kid, &bus->children, sibling) {
397 DeviceState *dev = kid->child;
398
399 if (dev->id && strcmp(dev->id, id) == 0) {
3418bd25 400 return dev;
0866aca1
AL
401 }
402
3418bd25
GH
403 QLIST_FOREACH(child, &dev->child_bus, sibling) {
404 ret = qdev_find_recursive(child, id);
405 if (ret) {
406 return ret;
407 }
408 }
409 }
410 return NULL;
411}
412
0d936928
AL
413/* FIXME move this logic into instance_init */
414static void do_qbus_create_inplace(BusState *bus, const char *typename,
415 DeviceState *parent, const char *name)
02e2da45 416{
d271de9f
GH
417 char *buf;
418 int i,len;
02e2da45 419
02e2da45 420 bus->parent = parent;
d271de9f
GH
421
422 if (name) {
423 /* use supplied name */
7267c094 424 bus->name = g_strdup(name);
d271de9f
GH
425 } else if (parent && parent->id) {
426 /* parent device has id -> use it for bus name */
427 len = strlen(parent->id) + 16;
7267c094 428 buf = g_malloc(len);
d271de9f
GH
429 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
430 bus->name = buf;
431 } else {
432 /* no id -> use lowercase bus type for bus name */
0d936928 433 len = strlen(typename) + 16;
7267c094 434 buf = g_malloc(len);
0d936928 435 len = snprintf(buf, len, "%s.%d", typename,
d271de9f
GH
436 parent ? parent->num_child_bus : 0);
437 for (i = 0; i < len; i++)
bb87ece5 438 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
439 bus->name = buf;
440 }
441
d8bb00d6 442 QTAILQ_INIT(&bus->children);
02e2da45 443 if (parent) {
72cf2d4f 444 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 445 parent->num_child_bus++;
f968fc68 446 object_property_add_child(OBJECT(parent), bus->name, OBJECT(bus), NULL);
8185d216 447 } else if (bus != sysbus_get_default()) {
80376c3f
IY
448 /* TODO: once all bus devices are qdevified,
449 only reset handler for main_system_bus should be registered here. */
450 qemu_register_reset(qbus_reset_all_fn, bus);
02e2da45 451 }
cd739fb6
GH
452}
453
0d936928
AL
454void qbus_create_inplace(BusState *bus, const char *typename,
455 DeviceState *parent, const char *name)
456{
457 object_initialize(bus, typename);
458 do_qbus_create_inplace(bus, typename, parent, name);
459}
460
461BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
cd739fb6
GH
462{
463 BusState *bus;
464
0d936928
AL
465 bus = BUS(object_new(typename));
466 bus->qom_allocated = true;
467 do_qbus_create_inplace(bus, typename, parent, name);
02e2da45
PB
468 return bus;
469}
cae4956e 470
131ec1bd
GH
471void qbus_free(BusState *bus)
472{
0866aca1 473 BusChild *kid;
131ec1bd 474
0866aca1
AL
475 while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
476 DeviceState *dev = kid->child;
131ec1bd
GH
477 qdev_free(dev);
478 }
479 if (bus->parent) {
480 QLIST_REMOVE(bus, sibling);
481 bus->parent->num_child_bus--;
80376c3f 482 } else {
8185d216 483 assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
80376c3f 484 qemu_unregister_reset(qbus_reset_all_fn, bus);
131ec1bd 485 }
7267c094 486 g_free((void*)bus->name);
0d936928
AL
487 if (bus->qom_allocated) {
488 object_delete(OBJECT(bus));
489 } else {
490 object_finalize(OBJECT(bus));
491 if (bus->glib_allocated) {
492 g_free(bus);
493 }
494 }
495}
496
497static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
498{
499 BusClass *bc = BUS_GET_CLASS(bus);
500
501 if (bc->get_fw_dev_path) {
502 return bc->get_fw_dev_path(dev);
131ec1bd 503 }
0d936928
AL
504
505 return NULL;
131ec1bd
GH
506}
507
1ca4d09a
GN
508static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
509{
510 int l = 0;
511
512 if (dev && dev->parent_bus) {
513 char *d;
514 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
0d936928
AL
515 d = bus_get_fw_dev_path(dev->parent_bus, dev);
516 if (d) {
1ca4d09a 517 l += snprintf(p + l, size - l, "%s", d);
7267c094 518 g_free(d);
1ca4d09a 519 } else {
f79f2bfc 520 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
1ca4d09a
GN
521 }
522 }
523 l += snprintf(p + l , size - l, "/");
524
525 return l;
526}
527
528char* qdev_get_fw_dev_path(DeviceState *dev)
529{
530 char path[128];
531 int l;
532
533 l = qdev_get_fw_dev_path_helper(dev, path, 128);
534
535 path[l-1] = '\0';
536
537 return strdup(path);
538}
85ed303b 539
09e5ab63
AL
540char *qdev_get_dev_path(DeviceState *dev)
541{
0d936928 542 BusClass *bc;
09e5ab63
AL
543
544 if (!dev || !dev->parent_bus) {
545 return NULL;
546 }
547
0d936928
AL
548 bc = BUS_GET_CLASS(dev->parent_bus);
549 if (bc->get_dev_path) {
550 return bc->get_dev_path(dev);
09e5ab63
AL
551 }
552
553 return NULL;
554}
555
a5296ca9
AL
556/**
557 * Legacy property handling
558 */
559
57c9fafe 560static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
a5296ca9
AL
561 const char *name, Error **errp)
562{
57c9fafe 563 DeviceState *dev = DEVICE(obj);
a5296ca9
AL
564 Property *prop = opaque;
565
e3cb6ba6
PB
566 char buffer[1024];
567 char *ptr = buffer;
a5296ca9 568
e3cb6ba6
PB
569 prop->info->print(dev, prop, buffer, sizeof(buffer));
570 visit_type_str(v, &ptr, name, errp);
a5296ca9
AL
571}
572
57c9fafe 573static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
a5296ca9
AL
574 const char *name, Error **errp)
575{
57c9fafe 576 DeviceState *dev = DEVICE(obj);
a5296ca9 577 Property *prop = opaque;
e3cb6ba6
PB
578 Error *local_err = NULL;
579 char *ptr = NULL;
580 int ret;
a5296ca9
AL
581
582 if (dev->state != DEV_STATE_CREATED) {
583 error_set(errp, QERR_PERMISSION_DENIED);
584 return;
585 }
586
e3cb6ba6
PB
587 visit_type_str(v, &ptr, name, &local_err);
588 if (local_err) {
589 error_propagate(errp, local_err);
590 return;
591 }
a5296ca9 592
e3cb6ba6 593 ret = prop->info->parse(dev, prop, ptr);
7db4c4e8 594 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
e3cb6ba6 595 g_free(ptr);
a5296ca9
AL
596}
597
598/**
599 * @qdev_add_legacy_property - adds a legacy property
600 *
601 * Do not use this is new code! Properties added through this interface will
ca2cc788 602 * be given names and types in the "legacy" namespace.
a5296ca9 603 *
68ee3569
PB
604 * Legacy properties are string versions of other OOM properties. The format
605 * of the string depends on the property type.
a5296ca9
AL
606 */
607void qdev_property_add_legacy(DeviceState *dev, Property *prop,
608 Error **errp)
609{
ca2cc788 610 gchar *name, *type;
a5296ca9 611
f3be016d
AL
612 /* Register pointer properties as legacy properties */
613 if (!prop->info->print && !prop->info->parse &&
614 (prop->info->set || prop->info->get)) {
68ee3569
PB
615 return;
616 }
f3be016d 617
ca2cc788 618 name = g_strdup_printf("legacy-%s", prop->name);
cafe5bdb
PB
619 type = g_strdup_printf("legacy<%s>",
620 prop->info->legacy_name ?: prop->info->name);
a5296ca9 621
57c9fafe 622 object_property_add(OBJECT(dev), name, type,
68ee3569
PB
623 prop->info->print ? qdev_get_legacy_property : prop->info->get,
624 prop->info->parse ? qdev_set_legacy_property : prop->info->set,
57c9fafe
AL
625 NULL,
626 prop, errp);
a5296ca9
AL
627
628 g_free(type);
ca2cc788
PB
629 g_free(name);
630}
631
632/**
633 * @qdev_property_add_static - add a @Property to a device.
634 *
635 * Static properties access data in a struct. The actual type of the
636 * property and the field depends on the property type.
637 */
638void qdev_property_add_static(DeviceState *dev, Property *prop,
639 Error **errp)
640{
fdae245f
PB
641 Error *local_err = NULL;
642 Object *obj = OBJECT(dev);
643
d822979b
PB
644 /*
645 * TODO qdev_prop_ptr does not have getters or setters. It must
646 * go now that it can be replaced with links. The test should be
647 * removed along with it: all static properties are read/write.
648 */
649 if (!prop->info->get && !prop->info->set) {
650 return;
651 }
652
fdae245f 653 object_property_add(obj, prop->name, prop->info->name,
57c9fafe 654 prop->info->get, prop->info->set,
dd0ba250 655 prop->info->release,
fdae245f
PB
656 prop, &local_err);
657
658 if (local_err) {
659 error_propagate(errp, local_err);
660 return;
661 }
662 if (prop->qtype == QTYPE_NONE) {
663 return;
664 }
665
666 if (prop->qtype == QTYPE_QBOOL) {
667 object_property_set_bool(obj, prop->defval, prop->name, &local_err);
668 } else if (prop->info->enum_table) {
669 object_property_set_str(obj, prop->info->enum_table[prop->defval],
670 prop->name, &local_err);
671 } else if (prop->qtype == QTYPE_QINT) {
672 object_property_set_int(obj, prop->defval, prop->name, &local_err);
673 }
674 assert_no_error(local_err);
6a146eba 675}
1de81d28 676
9674bfe4
AL
677static void device_initfn(Object *obj)
678{
679 DeviceState *dev = DEVICE(obj);
bce54474 680 ObjectClass *class;
9674bfe4
AL
681 Property *prop;
682
683 if (qdev_hotplug) {
684 dev->hotplugged = 1;
685 qdev_hot_added = true;
686 }
687
688 dev->instance_id_alias = -1;
9674bfe4
AL
689 dev->state = DEV_STATE_CREATED;
690
bce54474
PB
691 class = object_get_class(OBJECT(dev));
692 do {
693 for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
694 qdev_property_add_legacy(dev, prop, NULL);
695 qdev_property_add_static(dev, prop, NULL);
696 }
bce54474
PB
697 class = object_class_get_parent(class);
698 } while (class != object_class_by_name(TYPE_DEVICE));
4b3582b0 699 qdev_prop_set_globals(dev);
f968fc68
AL
700
701 object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
702 (Object **)&dev->parent_bus, NULL);
9674bfe4
AL
703}
704
60adba37
AL
705/* Unlink device from bus and free the structure. */
706static void device_finalize(Object *obj)
707{
708 DeviceState *dev = DEVICE(obj);
709 BusState *bus;
60adba37
AL
710 DeviceClass *dc = DEVICE_GET_CLASS(dev);
711
712 if (dev->state == DEV_STATE_INITIALIZED) {
713 while (dev->num_child_bus) {
714 bus = QLIST_FIRST(&dev->child_bus);
715 qbus_free(bus);
716 }
717 if (qdev_get_vmsd(dev)) {
718 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
719 }
720 if (dc->exit) {
721 dc->exit(dev);
722 }
723 if (dev->opts) {
724 qemu_opts_del(dev->opts);
725 }
726 }
0866aca1
AL
727 if (dev->parent_bus) {
728 bus_remove_child(dev->parent_bus, dev);
729 }
60adba37
AL
730}
731
bce54474
PB
732static void device_class_base_init(ObjectClass *class, void *data)
733{
734 DeviceClass *klass = DEVICE_CLASS(class);
735
736 /* We explicitly look up properties in the superclasses,
737 * so do not propagate them to the subclasses.
738 */
739 klass->props = NULL;
740}
741
94afdadc
AL
742void device_reset(DeviceState *dev)
743{
744 DeviceClass *klass = DEVICE_GET_CLASS(dev);
745
746 if (klass->reset) {
747 klass->reset(dev);
748 }
749}
750
f05f6b4a
PB
751Object *qdev_get_machine(void)
752{
753 static Object *dev;
754
755 if (dev == NULL) {
dfe47e70 756 dev = container_get(object_get_root(), "/machine");
f05f6b4a
PB
757 }
758
759 return dev;
760}
761
32fea402
AL
762static TypeInfo device_type_info = {
763 .name = TYPE_DEVICE,
764 .parent = TYPE_OBJECT,
765 .instance_size = sizeof(DeviceState),
9674bfe4 766 .instance_init = device_initfn,
60adba37 767 .instance_finalize = device_finalize,
bce54474 768 .class_base_init = device_class_base_init,
32fea402
AL
769 .abstract = true,
770 .class_size = sizeof(DeviceClass),
771};
772
0d936928
AL
773static const TypeInfo bus_info = {
774 .name = TYPE_BUS,
775 .parent = TYPE_OBJECT,
776 .instance_size = sizeof(BusState),
777 .abstract = true,
778 .class_size = sizeof(BusClass),
779};
780
83f7d43a 781static void qdev_register_types(void)
32fea402 782{
0d936928 783 type_register_static(&bus_info);
32fea402
AL
784 type_register_static(&device_type_info);
785}
786
83f7d43a 787type_init(qdev_register_types)