blob: e82165d7381dabc88f272a9c0f5b800860ffb8c6 [file] [log] [blame]
Paul Brookaae94602009-05-14 22:35:06 +01001/*
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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Paul Brookaae94602009-05-14 22:35:06 +010018 */
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
Paul Brook9d07d752009-05-14 22:35:07 +010028#include "net.h"
Paul Brookaae94602009-05-14 22:35:06 +010029#include "qdev.h"
30#include "sysemu.h"
31
Anthony Liguoriee46d8a2011-12-22 15:24:20 -060032int qdev_hotplug = 0;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070033static bool qdev_hot_added = false;
34static bool qdev_hot_removed = false;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020035
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020036/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000037static BusState *main_system_bus;
Isaku Yamahata2da8bb92011-08-02 10:59:13 +090038static void main_system_bus_create(void);
Paul Brook4d6ae672009-05-14 22:35:06 +010039
Paul Brookaae94602009-05-14 22:35:06 +010040/* Register a new device type. */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060041const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
42{
Anthony Liguori6e008582011-12-09 11:06:57 -060043 DeviceClass *dc = DEVICE_GET_CLASS(dev);
44 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060045}
46
47BusInfo *qdev_get_bus_info(DeviceState *dev)
48{
Anthony Liguori6e008582011-12-09 11:06:57 -060049 DeviceClass *dc = DEVICE_GET_CLASS(dev);
50 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060051}
52
53Property *qdev_get_props(DeviceState *dev)
54{
Anthony Liguori6e008582011-12-09 11:06:57 -060055 DeviceClass *dc = DEVICE_GET_CLASS(dev);
56 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060057}
58
59const char *qdev_fw_name(DeviceState *dev)
60{
Anthony Liguori6e008582011-12-09 11:06:57 -060061 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060062
Anthony Liguori6e008582011-12-09 11:06:57 -060063 if (dc->fw_name) {
64 return dc->fw_name;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060065 }
66
67 return object_get_typename(OBJECT(dev));
68}
69
Blue Swirla369da52011-09-27 19:15:42 +000070bool qdev_exists(const char *name)
71{
Anthony Liguori212ad112012-02-01 09:34:28 -060072 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +000073}
Anthony Liguori40021f02011-12-04 12:22:06 -060074
Paolo Bonzinica2cc782011-12-18 17:05:11 +010075static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
76 Error **errp);
77
Anthony Liguori9fbe6122011-12-22 15:14:27 -060078void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
Paul Brookaae94602009-05-14 22:35:06 +010079{
Anthony Liguoria5296ca2011-12-12 14:29:27 -060080 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010081
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020082 if (qdev_hotplug) {
83 assert(bus->allow_hotplug);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020084 }
Anthony Liguoria5296ca2011-12-12 14:29:27 -060085
Anthony Liguori9fbe6122011-12-22 15:14:27 -060086 dev->parent_bus = bus;
Anthony Liguori9674bfe2011-12-22 15:06:37 -060087 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060088
Anthony Liguori9fbe6122011-12-22 15:14:27 -060089 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Anthony Liguori6e008582011-12-09 11:06:57 -060090 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -060091 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +010092 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060093 }
Paul Brookaae94602009-05-14 22:35:06 +010094}
95
Markus Armbruster0c175422010-02-19 19:12:18 +010096/* Create a new device. This only initializes the device state structure
97 and allows properties to be set. qdev_init should be called to
98 initialize the actual device emulation. */
99DeviceState *qdev_create(BusState *bus, const char *name)
100{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000101 DeviceState *dev;
102
103 dev = qdev_try_create(bus, name);
104 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100105 if (bus) {
106 hw_error("Unknown device '%s' for bus '%s'\n", name,
107 bus->info->name);
108 } else {
109 hw_error("Unknown device '%s' for default sysbus\n", name);
110 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000111 }
112
113 return dev;
114}
115
116DeviceState *qdev_try_create(BusState *bus, const char *name)
117{
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600118 DeviceState *dev;
119
120 dev = DEVICE(object_new(name));
121 if (!dev) {
122 return NULL;
123 }
124
Markus Armbruster0c175422010-02-19 19:12:18 +0100125 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100126 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100127 }
128
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600129 qdev_set_parent_bus(dev, bus);
130 qdev_prop_set_globals(dev);
131
132 return dev;
Markus Armbruster0c175422010-02-19 19:12:18 +0100133}
134
Paul Brookaae94602009-05-14 22:35:06 +0100135/* Initialize a device. Device properties should be set before calling
136 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200137 calling this function.
138 On failure, destroy the device and return negative value.
139 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200140int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100141{
Anthony Liguori6e008582011-12-09 11:06:57 -0600142 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200143 int rc;
144
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200145 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600146
Anthony Liguorid307af72011-12-09 15:02:56 -0600147 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200148 if (rc < 0) {
149 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200150 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200151 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600152 if (qdev_get_vmsd(dev)) {
153 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200154 dev->instance_id_alias,
155 dev->alias_required_for_version);
156 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200157 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600158 if (dev->hotplugged) {
159 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200160 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200161 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100162}
163
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200164void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
165 int required_for_version)
166{
167 assert(dev->state == DEV_STATE_CREATED);
168 dev->instance_id_alias = alias_id;
169 dev->alias_required_for_version = required_for_version;
170}
171
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200172int qdev_unplug(DeviceState *dev)
173{
Anthony Liguori6e008582011-12-09 11:06:57 -0600174 DeviceClass *dc = DEVICE_GET_CLASS(dev);
175
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200176 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100177 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200178 return -1;
179 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600180 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530181
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700182 qdev_hot_removed = true;
183
Anthony Liguori6e008582011-12-09 11:06:57 -0600184 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200185}
186
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900187static int qdev_reset_one(DeviceState *dev, void *opaque)
188{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600189 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900190
191 return 0;
192}
193
194BusState *sysbus_get_default(void)
195{
Stefan Weil68694892010-12-16 19:33:22 +0100196 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900197 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100198 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900199 return main_system_bus;
200}
201
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900202static int qbus_reset_one(BusState *bus, void *opaque)
203{
204 if (bus->info->reset) {
205 return bus->info->reset(bus);
206 }
207 return 0;
208}
209
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900210void qdev_reset_all(DeviceState *dev)
211{
212 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
213}
214
Isaku Yamahata80376c32010-12-20 14:33:35 +0900215void qbus_reset_all_fn(void *opaque)
216{
217 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200218 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900219}
220
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200221/* can be used as ->unplug() callback for the simple cases */
222int qdev_simple_unplug_cb(DeviceState *dev)
223{
224 /* just zap it */
225 qdev_free(dev);
226 return 0;
227}
228
Michael Tokarev3b29a102011-04-06 17:51:59 +0400229
230/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200231 returning an error value. This is okay during machine creation.
232 Don't use for hotplug, because there callers need to recover from
233 failure. Exception: if you know the device's init() callback can't
234 fail, then qdev_init_nofail() can't fail either, and is therefore
235 usable even then. But relying on the device implementation that
236 way is somewhat unclean, and best avoided. */
237void qdev_init_nofail(DeviceState *dev)
238{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200239 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600240 error_report("Initialization of device %s failed",
241 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200242 exit(1);
243 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200244}
245
Anthony Liguori44677de2011-12-12 14:29:26 -0600246static void qdev_property_del_all(DeviceState *dev)
247{
248 while (!QTAILQ_EMPTY(&dev->properties)) {
249 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
250
251 QTAILQ_REMOVE(&dev->properties, prop, node);
252
253 if (prop->release) {
254 prop->release(dev, prop->name, prop->opaque);
255 }
256
257 g_free(prop->name);
258 g_free(prop->type);
259 g_free(prop);
260 }
261}
262
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600263static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
264{
265 DeviceProperty *prop;
266
267 QTAILQ_FOREACH(prop, &dev->properties, node) {
268 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
269 break;
270 }
271 }
272
273 g_assert(prop != NULL);
274
275 QTAILQ_REMOVE(&dev->properties, prop, node);
276
277 if (prop->release) {
278 prop->release(dev, prop->name, prop->opaque);
279 }
280
281 g_free(prop->name);
282 g_free(prop->type);
283 g_free(prop);
284}
285
Paul Brook02e2da42009-05-23 00:05:19 +0100286/* Unlink device from bus and free the structure. */
287void qdev_free(DeviceState *dev)
288{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200289 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200290 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600291 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200292
Anthony Liguori44677de2011-12-12 14:29:26 -0600293 qdev_property_del_all(dev);
294
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200295 if (dev->state == DEV_STATE_INITIALIZED) {
296 while (dev->num_child_bus) {
297 bus = QLIST_FIRST(&dev->child_bus);
298 qbus_free(bus);
299 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600300 if (qdev_get_vmsd(dev)) {
301 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
302 }
303 if (dc->exit) {
304 dc->exit(dev);
305 }
306 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200307 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600308 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200309 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200310 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600311 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200312 if (prop->info->free) {
313 prop->info->free(dev, prop);
314 }
315 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600316 if (dev->parent) {
317 qdev_property_del_child(dev->parent, dev, NULL);
318 }
319 if (dev->ref != 0) {
320 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
321 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600322 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100323}
324
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200325void qdev_machine_creation_done(void)
326{
327 /*
328 * ok, initial machine setup is done, starting from now we can
329 * only create hotpluggable devices
330 */
331 qdev_hotplug = 1;
332}
333
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700334bool qdev_machine_modified(void)
335{
336 return qdev_hot_added || qdev_hot_removed;
337}
338
Paul Brookaae94602009-05-14 22:35:06 +0100339/* Get a character (serial) device interface. */
340CharDriverState *qdev_init_chardev(DeviceState *dev)
341{
342 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530343
344 /* FIXME: This function needs to go away: use chardev properties! */
345 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100346}
347
Paul Brook02e2da42009-05-23 00:05:19 +0100348BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100349{
Paul Brook02e2da42009-05-23 00:05:19 +0100350 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100351}
352
Paul Brookaae94602009-05-14 22:35:06 +0100353void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
354{
355 assert(dev->num_gpio_in == 0);
356 dev->num_gpio_in = n;
357 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
358}
359
360void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
361{
362 assert(dev->num_gpio_out == 0);
363 dev->num_gpio_out = n;
364 dev->gpio_out = pins;
365}
366
367qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
368{
369 assert(n >= 0 && n < dev->num_gpio_in);
370 return dev->gpio_in[n];
371}
372
373void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
374{
375 assert(n >= 0 && n < dev->num_gpio_out);
376 dev->gpio_out[n] = pin;
377}
378
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200379void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
380{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200381 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200382 if (nd->vlan)
383 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
384 if (nd->netdev)
385 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530386 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200387 qdev_prop_exists(dev, "vectors")) {
388 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
389 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100390 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200391}
392
Paul Brook02e2da42009-05-23 00:05:19 +0100393BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100394{
Paul Brook02e2da42009-05-23 00:05:19 +0100395 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100396
Blue Swirl72cf2d42009-09-12 07:36:22 +0000397 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100398 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100399 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100400 }
401 }
402 return NULL;
403}
404
Anthony Liguori81699d82010-11-19 18:55:58 +0900405int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
406 qbus_walkerfn *busfn, void *opaque)
407{
408 DeviceState *dev;
409 int err;
410
411 if (busfn) {
412 err = busfn(bus, opaque);
413 if (err) {
414 return err;
415 }
416 }
417
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200418 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900419 err = qdev_walk_children(dev, devfn, busfn, opaque);
420 if (err < 0) {
421 return err;
422 }
423 }
424
425 return 0;
426}
427
428int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
429 qbus_walkerfn *busfn, void *opaque)
430{
431 BusState *bus;
432 int err;
433
434 if (devfn) {
435 err = devfn(dev, opaque);
436 if (err) {
437 return err;
438 }
439 }
440
441 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
442 err = qbus_walk_children(bus, devfn, busfn, opaque);
443 if (err < 0) {
444 return err;
445 }
446 }
447
448 return 0;
449}
450
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900451DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200452{
453 DeviceState *dev, *ret;
454 BusState *child;
455
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200456 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200457 if (dev->id && strcmp(dev->id, id) == 0)
458 return dev;
459 QLIST_FOREACH(child, &dev->child_bus, sibling) {
460 ret = qdev_find_recursive(child, id);
461 if (ret) {
462 return ret;
463 }
464 }
465 }
466 return NULL;
467}
468
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200469void qbus_create_inplace(BusState *bus, BusInfo *info,
470 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100471{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200472 char *buf;
473 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100474
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200475 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100476 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200477
478 if (name) {
479 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500480 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200481 } else if (parent && parent->id) {
482 /* parent device has id -> use it for bus name */
483 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500484 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200485 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
486 bus->name = buf;
487 } else {
488 /* no id -> use lowercase bus type for bus name */
489 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500490 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200491 len = snprintf(buf, len, "%s.%d", info->name,
492 parent ? parent->num_child_bus : 0);
493 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200494 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200495 bus->name = buf;
496 }
497
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200498 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100499 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000500 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200501 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900502 } else if (bus != main_system_bus) {
503 /* TODO: once all bus devices are qdevified,
504 only reset handler for main_system_bus should be registered here. */
505 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100506 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200507}
508
509BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
510{
511 BusState *bus;
512
Anthony Liguori7267c092011-08-20 22:09:37 -0500513 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200514 bus->qdev_allocated = 1;
515 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100516 return bus;
517}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100518
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900519static void main_system_bus_create(void)
520{
521 /* assign main_system_bus before qbus_create_inplace()
522 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500523 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900524 main_system_bus->qdev_allocated = 1;
525 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
526 "main-system-bus");
527}
528
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200529void qbus_free(BusState *bus)
530{
531 DeviceState *dev;
532
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200533 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200534 qdev_free(dev);
535 }
536 if (bus->parent) {
537 QLIST_REMOVE(bus, sibling);
538 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900539 } else {
540 assert(bus != main_system_bus); /* main_system_bus is never freed */
541 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200542 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500543 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200544 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500545 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200546 }
547}
548
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200549static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
550{
551 int l = 0;
552
553 if (dev && dev->parent_bus) {
554 char *d;
555 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
556 if (dev->parent_bus->info->get_fw_dev_path) {
557 d = dev->parent_bus->info->get_fw_dev_path(dev);
558 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500559 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200560 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600561 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200562 }
563 }
564 l += snprintf(p + l , size - l, "/");
565
566 return l;
567}
568
569char* qdev_get_fw_dev_path(DeviceState *dev)
570{
571 char path[128];
572 int l;
573
574 l = qdev_get_fw_dev_path_helper(dev, path, 128);
575
576 path[l-1] = '\0';
577
578 return strdup(path);
579}
Anthony Liguori85ed3032011-12-12 14:29:25 -0600580
Anthony Liguoricd34d662011-12-12 14:29:43 -0600581char *qdev_get_type(DeviceState *dev, Error **errp)
582{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600583 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -0600584}
585
Anthony Liguori85ed3032011-12-12 14:29:25 -0600586void qdev_ref(DeviceState *dev)
587{
588 dev->ref++;
589}
590
591void qdev_unref(DeviceState *dev)
592{
593 g_assert(dev->ref > 0);
594 dev->ref--;
595}
Anthony Liguori44677de2011-12-12 14:29:26 -0600596
597void qdev_property_add(DeviceState *dev, const char *name, const char *type,
598 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
599 DevicePropertyRelease *release,
600 void *opaque, Error **errp)
601{
602 DeviceProperty *prop = g_malloc0(sizeof(*prop));
603
604 prop->name = g_strdup(name);
605 prop->type = g_strdup(type);
606
607 prop->get = get;
608 prop->set = set;
609 prop->release = release;
610 prop->opaque = opaque;
611
612 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
613}
614
615static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
616{
617 DeviceProperty *prop;
618
619 QTAILQ_FOREACH(prop, &dev->properties, node) {
620 if (strcmp(prop->name, name) == 0) {
621 return prop;
622 }
623 }
624
625 return NULL;
626}
627
628void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
629 Error **errp)
630{
631 DeviceProperty *prop = qdev_property_find(dev, name);
632
633 if (prop == NULL) {
634 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
635 return;
636 }
637
638 if (!prop->get) {
639 error_set(errp, QERR_PERMISSION_DENIED);
640 } else {
641 prop->get(dev, v, prop->opaque, name, errp);
642 }
643}
644
645void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
646 Error **errp)
647{
648 DeviceProperty *prop = qdev_property_find(dev, name);
649
650 if (prop == NULL) {
651 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
652 return;
653 }
654
655 if (!prop->set) {
656 error_set(errp, QERR_PERMISSION_DENIED);
657 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +0100658 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -0600659 }
660}
661
662const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
663{
664 DeviceProperty *prop = qdev_property_find(dev, name);
665
666 if (prop == NULL) {
667 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
668 return NULL;
669 }
670
671 return prop->type;
672}
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600673
674/**
675 * Legacy property handling
676 */
677
678static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
679 const char *name, Error **errp)
680{
681 Property *prop = opaque;
682
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100683 char buffer[1024];
684 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600685
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100686 prop->info->print(dev, prop, buffer, sizeof(buffer));
687 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600688}
689
690static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
691 const char *name, Error **errp)
692{
693 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100694 Error *local_err = NULL;
695 char *ptr = NULL;
696 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600697
698 if (dev->state != DEV_STATE_CREATED) {
699 error_set(errp, QERR_PERMISSION_DENIED);
700 return;
701 }
702
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100703 visit_type_str(v, &ptr, name, &local_err);
704 if (local_err) {
705 error_propagate(errp, local_err);
706 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600707 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100708
709 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +0100710 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100711 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600712}
713
714/**
715 * @qdev_add_legacy_property - adds a legacy property
716 *
717 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100718 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600719 *
720 * Legacy properties are always processed as strings. The format of the string
721 * depends on the property type.
722 */
723void qdev_property_add_legacy(DeviceState *dev, Property *prop,
724 Error **errp)
725{
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100726 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600727
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100728 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100729 type = g_strdup_printf("legacy<%s>",
730 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600731
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100732 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100733 prop->info->print ? qdev_get_legacy_property : NULL,
734 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600735 NULL,
736 prop, errp);
737
738 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100739 g_free(name);
740}
741
742/**
743 * @qdev_property_add_static - add a @Property to a device.
744 *
745 * Static properties access data in a struct. The actual type of the
746 * property and the field depends on the property type.
747 */
748void qdev_property_add_static(DeviceState *dev, Property *prop,
749 Error **errp)
750{
751 qdev_property_add(dev, prop->name, prop->info->name,
752 prop->info->get, prop->info->set,
753 NULL,
754 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600755}
Anthony Liguoria10f07a2011-12-12 14:29:28 -0600756
757DeviceState *qdev_get_root(void)
758{
759 static DeviceState *qdev_root;
760
761 if (!qdev_root) {
762 qdev_root = qdev_create(NULL, "container");
763 qdev_init_nofail(qdev_root);
764 }
765
766 return qdev_root;
767}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -0600768
Anthony Liguori3de1c3e2011-12-12 14:29:31 -0600769static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
770 const char *name, Error **errp)
771{
772 DeviceState *child = opaque;
773 gchar *path;
774
775 path = qdev_get_canonical_path(child);
776 visit_type_str(v, &path, name, errp);
777 g_free(path);
778}
779
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600780static void qdev_release_child_property(DeviceState *dev, const char *name,
781 void *opaque)
782{
783 DeviceState *child = opaque;
784
785 qdev_unref(child);
786}
787
Anthony Liguori3de1c3e2011-12-12 14:29:31 -0600788void qdev_property_add_child(DeviceState *dev, const char *name,
789 DeviceState *child, Error **errp)
790{
791 gchar *type;
792
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600793 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -0600794
795 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600796 NULL, qdev_release_child_property,
797 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -0600798
799 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -0600800 g_assert(child->parent == NULL);
801 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -0600802
803 g_free(type);
804}
805
Anthony Liguori83e94fb2011-12-12 14:29:32 -0600806static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
807 const char *name, Error **errp)
808{
809 DeviceState **child = opaque;
810 gchar *path;
811
812 if (*child) {
813 path = qdev_get_canonical_path(*child);
814 visit_type_str(v, &path, name, errp);
815 g_free(path);
816 } else {
817 path = (gchar *)"";
818 visit_type_str(v, &path, name, errp);
819 }
820}
821
822static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
823 const char *name, Error **errp)
824{
825 DeviceState **child = opaque;
826 bool ambiguous = false;
827 const char *type;
828 char *path;
829
830 type = qdev_property_get_type(dev, name, NULL);
831
832 visit_type_str(v, &path, name, errp);
833
834 if (*child) {
835 qdev_unref(*child);
836 }
837
838 if (strcmp(path, "") != 0) {
839 DeviceState *target;
840
841 target = qdev_resolve_path(path, &ambiguous);
842 if (target) {
843 gchar *target_type;
844
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600845 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -0600846 if (strcmp(target_type, type) == 0) {
847 *child = target;
848 qdev_ref(target);
849 } else {
850 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
851 }
852
853 g_free(target_type);
854 } else {
855 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
856 }
857 } else {
858 *child = NULL;
859 }
860
861 g_free(path);
862}
863
864void qdev_property_add_link(DeviceState *dev, const char *name,
865 const char *type, DeviceState **child,
866 Error **errp)
867{
868 gchar *full_type;
869
870 full_type = g_strdup_printf("link<%s>", type);
871
872 qdev_property_add(dev, name, full_type,
873 qdev_get_link_property,
874 qdev_set_link_property,
875 NULL, child, errp);
876
877 g_free(full_type);
878}
879
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -0600880gchar *qdev_get_canonical_path(DeviceState *dev)
881{
Anthony Liguorib2b6c392011-12-12 14:29:40 -0600882 DeviceState *root = qdev_get_root();
883 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -0600884
Anthony Liguorib2b6c392011-12-12 14:29:40 -0600885 while (dev != root) {
886 DeviceProperty *prop = NULL;
887
888 g_assert(dev->parent != NULL);
889
890 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
891 if (!strstart(prop->type, "child<", NULL)) {
892 continue;
893 }
894
895 if (prop->opaque == dev) {
896 if (path) {
897 newpath = g_strdup_printf("%s/%s", prop->name, path);
898 g_free(path);
899 path = newpath;
900 } else {
901 path = g_strdup(prop->name);
902 }
903 break;
904 }
905 }
906
907 g_assert(prop != NULL);
908
909 dev = dev->parent;
910 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -0600911
912 newpath = g_strdup_printf("/%s", path);
913 g_free(path);
914
915 return newpath;
916}
Anthony Liguoridc45c212011-12-12 14:29:30 -0600917
918static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
919 gchar **parts,
920 int index)
921{
922 DeviceProperty *prop;
923 DeviceState *child;
924
925 if (parts[index] == NULL) {
926 return parent;
927 }
928
929 if (strcmp(parts[index], "") == 0) {
930 return qdev_resolve_abs_path(parent, parts, index + 1);
931 }
932
933 prop = qdev_property_find(parent, parts[index]);
934 if (prop == NULL) {
935 return NULL;
936 }
937
938 child = NULL;
939 if (strstart(prop->type, "link<", NULL)) {
940 DeviceState **pchild = prop->opaque;
941 if (*pchild) {
942 child = *pchild;
943 }
944 } else if (strstart(prop->type, "child<", NULL)) {
945 child = prop->opaque;
946 }
947
948 if (!child) {
949 return NULL;
950 }
951
952 return qdev_resolve_abs_path(child, parts, index + 1);
953}
954
955static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
956 gchar **parts,
957 bool *ambiguous)
958{
959 DeviceState *dev;
960 DeviceProperty *prop;
961
962 dev = qdev_resolve_abs_path(parent, parts, 0);
963
964 QTAILQ_FOREACH(prop, &parent->properties, node) {
965 DeviceState *found;
966
967 if (!strstart(prop->type, "child<", NULL)) {
968 continue;
969 }
970
971 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
972 if (found) {
973 if (dev) {
974 if (ambiguous) {
975 *ambiguous = true;
976 }
977 return NULL;
978 }
979 dev = found;
980 }
981
982 if (ambiguous && *ambiguous) {
983 return NULL;
984 }
985 }
986
987 return dev;
988}
989
990DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
991{
992 bool partial_path = true;
993 DeviceState *dev;
994 gchar **parts;
995
996 parts = g_strsplit(path, "/", 0);
997 if (parts == NULL || parts[0] == NULL) {
998 g_strfreev(parts);
999 return qdev_get_root();
1000 }
1001
1002 if (strcmp(parts[0], "") == 0) {
1003 partial_path = false;
1004 }
1005
1006 if (partial_path) {
1007 if (ambiguous) {
1008 *ambiguous = false;
1009 }
1010 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1011 } else {
1012 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1013 }
1014
1015 g_strfreev(parts);
1016
1017 return dev;
1018}
1019
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001020typedef struct StringProperty
1021{
1022 char *(*get)(DeviceState *, Error **);
1023 void (*set)(DeviceState *, const char *, Error **);
1024} StringProperty;
1025
1026static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1027 const char *name, Error **errp)
1028{
1029 StringProperty *prop = opaque;
1030 char *value;
1031
1032 value = prop->get(dev, errp);
1033 if (value) {
1034 visit_type_str(v, &value, name, errp);
1035 g_free(value);
1036 }
1037}
1038
1039static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1040 const char *name, Error **errp)
1041{
1042 StringProperty *prop = opaque;
1043 char *value;
1044 Error *local_err = NULL;
1045
1046 visit_type_str(v, &value, name, &local_err);
1047 if (local_err) {
1048 error_propagate(errp, local_err);
1049 return;
1050 }
1051
1052 prop->set(dev, value, errp);
1053 g_free(value);
1054}
1055
1056static void qdev_property_release_str(DeviceState *dev, const char *name,
1057 void *opaque)
1058{
1059 StringProperty *prop = opaque;
1060 g_free(prop);
1061}
1062
1063void qdev_property_add_str(DeviceState *dev, const char *name,
1064 char *(*get)(DeviceState *, Error **),
1065 void (*set)(DeviceState *, const char *, Error **),
1066 Error **errp)
1067{
1068 StringProperty *prop = g_malloc0(sizeof(*prop));
1069
1070 prop->get = get;
1071 prop->set = set;
1072
1073 qdev_property_add(dev, name, "string",
1074 get ? qdev_property_get_str : NULL,
1075 set ? qdev_property_set_str : NULL,
1076 qdev_property_release_str,
1077 prop, errp);
1078}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001079
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001080static void device_initfn(Object *obj)
1081{
1082 DeviceState *dev = DEVICE(obj);
1083 Property *prop;
1084
1085 if (qdev_hotplug) {
1086 dev->hotplugged = 1;
1087 qdev_hot_added = true;
1088 }
1089
1090 dev->instance_id_alias = -1;
1091 QTAILQ_INIT(&dev->properties);
1092 dev->state = DEV_STATE_CREATED;
1093
1094 qdev_prop_set_defaults(dev, qdev_get_props(dev));
1095 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
1096 qdev_property_add_legacy(dev, prop, NULL);
1097 qdev_property_add_static(dev, prop, NULL);
1098 }
1099
1100 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
1101}
1102
Anthony Liguori94afdad2011-12-04 11:36:01 -06001103void device_reset(DeviceState *dev)
1104{
1105 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1106
1107 if (klass->reset) {
1108 klass->reset(dev);
1109 }
1110}
1111
Anthony Liguori32fea402011-12-16 14:34:46 -06001112static TypeInfo device_type_info = {
1113 .name = TYPE_DEVICE,
1114 .parent = TYPE_OBJECT,
1115 .instance_size = sizeof(DeviceState),
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001116 .instance_init = device_initfn,
Anthony Liguori32fea402011-12-16 14:34:46 -06001117 .abstract = true,
1118 .class_size = sizeof(DeviceClass),
1119};
1120
1121static void init_qdev(void)
1122{
1123 type_register_static(&device_type_info);
1124}
1125
1126device_init(init_qdev);