blob: 4f6c3a713a098c3bf9a5655793dbc9002b36cbf2 [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"
Gerd Hoffmanncae49562009-06-05 15:53:17 +010031#include "monitor.h"
Paul Brookaae94602009-05-14 22:35:06 +010032
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020033static int qdev_hotplug = 0;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070034static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020036
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020037/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000038static BusState *main_system_bus;
Isaku Yamahata2da8bb92011-08-02 10:59:13 +090039static void main_system_bus_create(void);
Paul Brook4d6ae672009-05-14 22:35:06 +010040
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020041static BusState *qbus_find_recursive(BusState *bus, const char *name,
42 const BusInfo *info);
43static BusState *qbus_find(const char *path);
44
Paul Brookaae94602009-05-14 22:35:06 +010045/* Register a new device type. */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060046const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
47{
Anthony Liguori6e008582011-12-09 11:06:57 -060048 DeviceClass *dc = DEVICE_GET_CLASS(dev);
49 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060050}
51
52BusInfo *qdev_get_bus_info(DeviceState *dev)
53{
Anthony Liguori6e008582011-12-09 11:06:57 -060054 DeviceClass *dc = DEVICE_GET_CLASS(dev);
55 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060056}
57
58Property *qdev_get_props(DeviceState *dev)
59{
Anthony Liguori6e008582011-12-09 11:06:57 -060060 DeviceClass *dc = DEVICE_GET_CLASS(dev);
61 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060062}
63
64const char *qdev_fw_name(DeviceState *dev)
65{
Anthony Liguori6e008582011-12-09 11:06:57 -060066 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060067
Anthony Liguori6e008582011-12-09 11:06:57 -060068 if (dc->fw_name) {
69 return dc->fw_name;
70 } else if (dc->alias) {
71 return dc->alias;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060072 }
73
74 return object_get_typename(OBJECT(dev));
75}
76
Blue Swirla369da52011-09-27 19:15:42 +000077bool qdev_exists(const char *name)
78{
Anthony Liguori212ad112012-02-01 09:34:28 -060079 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +000080}
Anthony Liguori40021f02011-12-04 12:22:06 -060081
Paolo Bonzinica2cc782011-12-18 17:05:11 +010082static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
83 Error **errp);
84
Anthony Liguori18b6dad2011-12-09 12:08:01 -060085static DeviceState *qdev_create_from_info(BusState *bus, const char *typename)
Paul Brookaae94602009-05-14 22:35:06 +010086{
Paul Brookaae94602009-05-14 22:35:06 +010087 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -060088 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010089
Anthony Liguori18b6dad2011-12-09 12:08:01 -060090 dev = DEVICE(object_new(typename));
Paul Brook02e2da42009-05-23 00:05:19 +010091 dev->parent_bus = bus;
Anthony Liguori6e008582011-12-09 11:06:57 -060092 qdev_prop_set_defaults(dev, qdev_get_props(dev));
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020093 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010094 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +020095 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020096 if (qdev_hotplug) {
97 assert(bus->allow_hotplug);
98 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070099 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200100 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200101 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600102 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200103 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600104
Anthony Liguori6e008582011-12-09 11:06:57 -0600105 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600106 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100107 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600108 }
109
Anthony Liguori6e008582011-12-09 11:06:57 -0600110 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600111 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100112 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600113 }
114
Anthony Liguoricd34d662011-12-12 14:29:43 -0600115 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
116
Paul Brookaae94602009-05-14 22:35:06 +0100117 return dev;
118}
119
Markus Armbruster0c175422010-02-19 19:12:18 +0100120/* Create a new device. This only initializes the device state structure
121 and allows properties to be set. qdev_init should be called to
122 initialize the actual device emulation. */
123DeviceState *qdev_create(BusState *bus, const char *name)
124{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000125 DeviceState *dev;
126
127 dev = qdev_try_create(bus, name);
128 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100129 if (bus) {
130 hw_error("Unknown device '%s' for bus '%s'\n", name,
131 bus->info->name);
132 } else {
133 hw_error("Unknown device '%s' for default sysbus\n", name);
134 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000135 }
136
137 return dev;
138}
139
140DeviceState *qdev_try_create(BusState *bus, const char *name)
141{
Markus Armbruster0c175422010-02-19 19:12:18 +0100142 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100143 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100144 }
145
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600146 return qdev_create_from_info(bus, name);
Markus Armbruster0c175422010-02-19 19:12:18 +0100147}
148
Anthony Liguori212ad112012-02-01 09:34:28 -0600149static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200150{
Anthony Liguori212ad112012-02-01 09:34:28 -0600151 DeviceClass *dc;
152 bool *show_no_user = opaque;
153
154 dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
155
156 if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
157 return;
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200158 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600159
160 error_printf("name \"%s\"", object_class_get_name(klass));
161 if (dc->bus_info) {
162 error_printf(", bus %s", dc->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200163 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600164 if (dc->alias) {
165 error_printf(", alias \"%s\"", dc->alias);
166 }
167 if (dc->desc) {
168 error_printf(", desc \"%s\"", dc->desc);
169 }
170 if (dc->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100171 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200172 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100173 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200174}
175
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200176static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200177{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200178 DeviceState *dev = opaque;
179
180 if (strcmp(name, "driver") == 0)
181 return 0;
182 if (strcmp(name, "bus") == 0)
183 return 0;
184
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100185 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200186 return -1;
187 }
188 return 0;
189}
190
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100191int qdev_device_help(QemuOpts *opts)
192{
193 const char *driver;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100194 Property *prop;
Anthony Liguori212ad112012-02-01 09:34:28 -0600195 ObjectClass *klass;
196 DeviceClass *info;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100197
198 driver = qemu_opt_get(opts, "driver");
199 if (driver && !strcmp(driver, "?")) {
Anthony Liguori212ad112012-02-01 09:34:28 -0600200 bool show_no_user = false;
201 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100202 return 1;
203 }
204
Markus Armbruster542379f2011-11-08 11:00:38 +0100205 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100206 return 0;
207 }
208
Anthony Liguori212ad112012-02-01 09:34:28 -0600209 klass = object_class_by_name(driver);
210 if (!klass) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100211 return 0;
212 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600213 info = DEVICE_CLASS(klass);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100214
215 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100216 /*
217 * TODO Properties without a parser are just for dirty hacks.
218 * qdev_prop_ptr is the only such PropertyInfo. It's marked
219 * for removal. This conditional should be removed along with
220 * it.
221 */
222 if (!prop->info->parse) {
223 continue; /* no way to set it, don't show */
224 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600225 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100226 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100227 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200228 for (prop = info->bus_info->props; prop && prop->name; prop++) {
229 if (!prop->info->parse) {
230 continue; /* no way to set it, don't show */
231 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600232 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100233 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200234 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100235 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100236}
237
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600238static DeviceState *qdev_get_peripheral(void)
239{
240 static DeviceState *dev;
241
242 if (dev == NULL) {
243 dev = qdev_create(NULL, "container");
244 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
245 qdev_init_nofail(dev);
246 }
247
248 return dev;
249}
250
Anthony Liguori8eb02832011-12-12 14:29:37 -0600251static DeviceState *qdev_get_peripheral_anon(void)
252{
253 static DeviceState *dev;
254
255 if (dev == NULL) {
256 dev = qdev_create(NULL, "container");
257 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
258 qdev_init_nofail(dev);
259 }
260
261 return dev;
262}
263
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200264DeviceState *qdev_device_add(QemuOpts *opts)
265{
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600266 DeviceClass *k;
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200267 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200268 DeviceState *qdev;
269 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200270
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200271 driver = qemu_opt_get(opts, "driver");
272 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100273 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200274 return NULL;
275 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200276
277 /* find driver */
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600278 k = DEVICE_CLASS(object_class_by_name(driver));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200279
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200280 /* find bus */
281 path = qemu_opt_get(opts, "bus");
282 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200283 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100284 if (!bus) {
285 return NULL;
286 }
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600287 if (bus->info != k->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100288 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
289 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100290 return NULL;
291 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200292 } else {
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600293 bus = qbus_find_recursive(main_system_bus, NULL, k->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100294 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100295 qerror_report(QERR_NO_BUS_FOR_DEVICE,
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600296 driver, k->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100297 return NULL;
298 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200299 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200300 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100301 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200302 return NULL;
303 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200304
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200305 /* create device, set properties */
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600306 qdev = qdev_create_from_info(bus, driver);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200307 id = qemu_opts_id(opts);
308 if (id) {
309 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600310 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600311 } else {
312 static int anon_count;
313 gchar *name = g_strdup_printf("device[%d]", anon_count++);
314 qdev_property_add_child(qdev_get_peripheral_anon(), name,
315 qdev, NULL);
316 g_free(name);
317 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200318 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
319 qdev_free(qdev);
320 return NULL;
321 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200322 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100323 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200324 return NULL;
325 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200326 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200327 return qdev;
328}
329
Paul Brookaae94602009-05-14 22:35:06 +0100330/* Initialize a device. Device properties should be set before calling
331 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200332 calling this function.
333 On failure, destroy the device and return negative value.
334 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200335int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100336{
Anthony Liguori6e008582011-12-09 11:06:57 -0600337 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200338 int rc;
339
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200340 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600341
Anthony Liguorid307af72011-12-09 15:02:56 -0600342 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200343 if (rc < 0) {
344 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200345 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200346 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600347 if (qdev_get_vmsd(dev)) {
348 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200349 dev->instance_id_alias,
350 dev->alias_required_for_version);
351 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200352 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600353 if (dev->hotplugged) {
354 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200355 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200356 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100357}
358
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200359void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
360 int required_for_version)
361{
362 assert(dev->state == DEV_STATE_CREATED);
363 dev->instance_id_alias = alias_id;
364 dev->alias_required_for_version = required_for_version;
365}
366
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200367int qdev_unplug(DeviceState *dev)
368{
Anthony Liguori6e008582011-12-09 11:06:57 -0600369 DeviceClass *dc = DEVICE_GET_CLASS(dev);
370
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200371 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100372 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200373 return -1;
374 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600375 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530376
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700377 qdev_hot_removed = true;
378
Anthony Liguori6e008582011-12-09 11:06:57 -0600379 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200380}
381
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900382static int qdev_reset_one(DeviceState *dev, void *opaque)
383{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600384 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900385
386 return 0;
387}
388
389BusState *sysbus_get_default(void)
390{
Stefan Weil68694892010-12-16 19:33:22 +0100391 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900392 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100393 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900394 return main_system_bus;
395}
396
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900397static int qbus_reset_one(BusState *bus, void *opaque)
398{
399 if (bus->info->reset) {
400 return bus->info->reset(bus);
401 }
402 return 0;
403}
404
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900405void qdev_reset_all(DeviceState *dev)
406{
407 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
408}
409
Isaku Yamahata80376c32010-12-20 14:33:35 +0900410void qbus_reset_all_fn(void *opaque)
411{
412 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200413 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900414}
415
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200416/* can be used as ->unplug() callback for the simple cases */
417int qdev_simple_unplug_cb(DeviceState *dev)
418{
419 /* just zap it */
420 qdev_free(dev);
421 return 0;
422}
423
Michael Tokarev3b29a102011-04-06 17:51:59 +0400424
425/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200426 returning an error value. This is okay during machine creation.
427 Don't use for hotplug, because there callers need to recover from
428 failure. Exception: if you know the device's init() callback can't
429 fail, then qdev_init_nofail() can't fail either, and is therefore
430 usable even then. But relying on the device implementation that
431 way is somewhat unclean, and best avoided. */
432void qdev_init_nofail(DeviceState *dev)
433{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200434 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600435 error_report("Initialization of device %s failed",
436 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200437 exit(1);
438 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200439}
440
Anthony Liguori44677de2011-12-12 14:29:26 -0600441static void qdev_property_del_all(DeviceState *dev)
442{
443 while (!QTAILQ_EMPTY(&dev->properties)) {
444 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
445
446 QTAILQ_REMOVE(&dev->properties, prop, node);
447
448 if (prop->release) {
449 prop->release(dev, prop->name, prop->opaque);
450 }
451
452 g_free(prop->name);
453 g_free(prop->type);
454 g_free(prop);
455 }
456}
457
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600458static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
459{
460 DeviceProperty *prop;
461
462 QTAILQ_FOREACH(prop, &dev->properties, node) {
463 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
464 break;
465 }
466 }
467
468 g_assert(prop != NULL);
469
470 QTAILQ_REMOVE(&dev->properties, prop, node);
471
472 if (prop->release) {
473 prop->release(dev, prop->name, prop->opaque);
474 }
475
476 g_free(prop->name);
477 g_free(prop->type);
478 g_free(prop);
479}
480
Paul Brook02e2da42009-05-23 00:05:19 +0100481/* Unlink device from bus and free the structure. */
482void qdev_free(DeviceState *dev)
483{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200484 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200485 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600486 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200487
Anthony Liguori44677de2011-12-12 14:29:26 -0600488 qdev_property_del_all(dev);
489
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200490 if (dev->state == DEV_STATE_INITIALIZED) {
491 while (dev->num_child_bus) {
492 bus = QLIST_FIRST(&dev->child_bus);
493 qbus_free(bus);
494 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600495 if (qdev_get_vmsd(dev)) {
496 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
497 }
498 if (dc->exit) {
499 dc->exit(dev);
500 }
501 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200502 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600503 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200504 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200505 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600506 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200507 if (prop->info->free) {
508 prop->info->free(dev, prop);
509 }
510 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600511 if (dev->parent) {
512 qdev_property_del_child(dev->parent, dev, NULL);
513 }
514 if (dev->ref != 0) {
515 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
516 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600517 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100518}
519
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200520void qdev_machine_creation_done(void)
521{
522 /*
523 * ok, initial machine setup is done, starting from now we can
524 * only create hotpluggable devices
525 */
526 qdev_hotplug = 1;
527}
528
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700529bool qdev_machine_modified(void)
530{
531 return qdev_hot_added || qdev_hot_removed;
532}
533
Paul Brookaae94602009-05-14 22:35:06 +0100534/* Get a character (serial) device interface. */
535CharDriverState *qdev_init_chardev(DeviceState *dev)
536{
537 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530538
539 /* FIXME: This function needs to go away: use chardev properties! */
540 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100541}
542
Paul Brook02e2da42009-05-23 00:05:19 +0100543BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100544{
Paul Brook02e2da42009-05-23 00:05:19 +0100545 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100546}
547
Paul Brookaae94602009-05-14 22:35:06 +0100548void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
549{
550 assert(dev->num_gpio_in == 0);
551 dev->num_gpio_in = n;
552 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
553}
554
555void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
556{
557 assert(dev->num_gpio_out == 0);
558 dev->num_gpio_out = n;
559 dev->gpio_out = pins;
560}
561
562qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
563{
564 assert(n >= 0 && n < dev->num_gpio_in);
565 return dev->gpio_in[n];
566}
567
568void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
569{
570 assert(n >= 0 && n < dev->num_gpio_out);
571 dev->gpio_out[n] = pin;
572}
573
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200574void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
575{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200576 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200577 if (nd->vlan)
578 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
579 if (nd->netdev)
580 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530581 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200582 qdev_prop_exists(dev, "vectors")) {
583 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
584 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100585 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200586}
587
Paul Brook02e2da42009-05-23 00:05:19 +0100588BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100589{
Paul Brook02e2da42009-05-23 00:05:19 +0100590 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100591
Blue Swirl72cf2d42009-09-12 07:36:22 +0000592 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100593 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100594 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100595 }
596 }
597 return NULL;
598}
599
Anthony Liguori81699d82010-11-19 18:55:58 +0900600int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
601 qbus_walkerfn *busfn, void *opaque)
602{
603 DeviceState *dev;
604 int err;
605
606 if (busfn) {
607 err = busfn(bus, opaque);
608 if (err) {
609 return err;
610 }
611 }
612
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200613 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900614 err = qdev_walk_children(dev, devfn, busfn, opaque);
615 if (err < 0) {
616 return err;
617 }
618 }
619
620 return 0;
621}
622
623int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
624 qbus_walkerfn *busfn, void *opaque)
625{
626 BusState *bus;
627 int err;
628
629 if (devfn) {
630 err = devfn(dev, opaque);
631 if (err) {
632 return err;
633 }
634 }
635
636 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
637 err = qbus_walk_children(bus, devfn, busfn, opaque);
638 if (err < 0) {
639 return err;
640 }
641 }
642
643 return 0;
644}
645
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200646static BusState *qbus_find_recursive(BusState *bus, const char *name,
647 const BusInfo *info)
648{
649 DeviceState *dev;
650 BusState *child, *ret;
651 int match = 1;
652
653 if (name && (strcmp(bus->name, name) != 0)) {
654 match = 0;
655 }
656 if (info && (bus->info != info)) {
657 match = 0;
658 }
659 if (match) {
660 return bus;
661 }
662
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200663 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000664 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200665 ret = qbus_find_recursive(child, name, info);
666 if (ret) {
667 return ret;
668 }
669 }
670 }
671 return NULL;
672}
673
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900674DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200675{
676 DeviceState *dev, *ret;
677 BusState *child;
678
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200679 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200680 if (dev->id && strcmp(dev->id, id) == 0)
681 return dev;
682 QLIST_FOREACH(child, &dev->child_bus, sibling) {
683 ret = qdev_find_recursive(child, id);
684 if (ret) {
685 return ret;
686 }
687 }
688 }
689 return NULL;
690}
691
Markus Armbruster53db16b2010-02-18 18:55:59 +0100692static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200693{
694 BusState *child;
695 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200696
Markus Armbruster53db16b2010-02-18 18:55:59 +0100697 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600698 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000699 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100700 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200701 sep = ", ";
702 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100703 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200704}
705
Markus Armbruster53db16b2010-02-18 18:55:59 +0100706static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200707{
708 DeviceState *dev;
709 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200710
Markus Armbruster53db16b2010-02-18 18:55:59 +0100711 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200712 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600713 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200714 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100715 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200716 sep = ", ";
717 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100718 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200719}
720
721static BusState *qbus_find_bus(DeviceState *dev, char *elem)
722{
723 BusState *child;
724
Blue Swirl72cf2d42009-09-12 07:36:22 +0000725 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200726 if (strcmp(child->name, elem) == 0) {
727 return child;
728 }
729 }
730 return NULL;
731}
732
733static DeviceState *qbus_find_dev(BusState *bus, char *elem)
734{
735 DeviceState *dev;
736
737 /*
738 * try to match in order:
739 * (1) instance id, if present
740 * (2) driver name
741 * (3) driver alias, if present
742 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200743 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200744 if (dev->id && strcmp(dev->id, elem) == 0) {
745 return dev;
746 }
747 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200748 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600749 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200750 return dev;
751 }
752 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200753 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600754 DeviceClass *dc = DEVICE_GET_CLASS(dev);
755
756 if (dc->alias && strcmp(dc->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200757 return dev;
758 }
759 }
760 return NULL;
761}
762
763static BusState *qbus_find(const char *path)
764{
765 DeviceState *dev;
766 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100767 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200768 int pos, len;
769
770 /* find start element */
771 if (path[0] == '/') {
772 bus = main_system_bus;
773 pos = 0;
774 } else {
775 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100776 assert(!path[0]);
777 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200778 }
779 bus = qbus_find_recursive(main_system_bus, elem, NULL);
780 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100781 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200782 return NULL;
783 }
784 pos = len;
785 }
786
787 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100788 assert(path[pos] == '/' || !path[pos]);
789 while (path[pos] == '/') {
790 pos++;
791 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200792 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200793 return bus;
794 }
795
796 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100797 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
798 assert(0);
799 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200800 }
801 pos += len;
802 dev = qbus_find_dev(bus, elem);
803 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100804 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100805 if (!monitor_cur_is_qmp()) {
806 qbus_list_dev(bus);
807 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200808 return NULL;
809 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100810
811 assert(path[pos] == '/' || !path[pos]);
812 while (path[pos] == '/') {
813 pos++;
814 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200815 if (path[pos] == '\0') {
816 /* last specified element is a device. If it has exactly
817 * one child bus accept it nevertheless */
818 switch (dev->num_child_bus) {
819 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100820 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200821 return NULL;
822 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000823 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200824 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100825 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100826 if (!monitor_cur_is_qmp()) {
827 qbus_list_bus(dev);
828 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200829 return NULL;
830 }
831 }
832
833 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100834 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
835 assert(0);
836 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200837 }
838 pos += len;
839 bus = qbus_find_bus(dev, elem);
840 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100841 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100842 if (!monitor_cur_is_qmp()) {
843 qbus_list_bus(dev);
844 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200845 return NULL;
846 }
847 }
848}
849
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200850void qbus_create_inplace(BusState *bus, BusInfo *info,
851 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100852{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200853 char *buf;
854 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100855
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200856 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100857 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200858
859 if (name) {
860 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500861 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200862 } else if (parent && parent->id) {
863 /* parent device has id -> use it for bus name */
864 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500865 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200866 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
867 bus->name = buf;
868 } else {
869 /* no id -> use lowercase bus type for bus name */
870 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500871 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200872 len = snprintf(buf, len, "%s.%d", info->name,
873 parent ? parent->num_child_bus : 0);
874 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200875 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200876 bus->name = buf;
877 }
878
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200879 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100880 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000881 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200882 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900883 } else if (bus != main_system_bus) {
884 /* TODO: once all bus devices are qdevified,
885 only reset handler for main_system_bus should be registered here. */
886 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100887 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200888}
889
890BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
891{
892 BusState *bus;
893
Anthony Liguori7267c092011-08-20 22:09:37 -0500894 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200895 bus->qdev_allocated = 1;
896 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100897 return bus;
898}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100899
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900900static void main_system_bus_create(void)
901{
902 /* assign main_system_bus before qbus_create_inplace()
903 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500904 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900905 main_system_bus->qdev_allocated = 1;
906 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
907 "main-system-bus");
908}
909
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200910void qbus_free(BusState *bus)
911{
912 DeviceState *dev;
913
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200914 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200915 qdev_free(dev);
916 }
917 if (bus->parent) {
918 QLIST_REMOVE(bus, sibling);
919 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900920 } else {
921 assert(bus != main_system_bus); /* main_system_bus is never freed */
922 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200923 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500924 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200925 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500926 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200927 }
928}
929
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100930#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
931static void qbus_print(Monitor *mon, BusState *bus, int indent);
932
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200933static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
934 const char *prefix, int indent)
935{
936 char buf[64];
937
938 if (!props)
939 return;
940 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100941 /*
942 * TODO Properties without a print method are just for dirty
943 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
944 * marked for removal. The test props->info->print should be
945 * removed along with it.
946 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200947 if (props->info->print) {
948 props->info->print(dev, props, buf, sizeof(buf));
949 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
950 }
951 props++;
952 }
953}
954
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100955static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
956{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100957 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600958 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200959 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100960 indent += 2;
961 if (dev->num_gpio_in) {
962 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
963 }
964 if (dev->num_gpio_out) {
965 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
966 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600967 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200968 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200969 if (dev->parent_bus->info->print_dev)
970 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000971 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100972 qbus_print(mon, child, indent);
973 }
974}
975
976static void qbus_print(Monitor *mon, BusState *bus, int indent)
977{
978 struct DeviceState *dev;
979
980 qdev_printf("bus: %s\n", bus->name);
981 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200982 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200983 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100984 qdev_print(mon, dev, indent);
985 }
986}
987#undef qdev_printf
988
989void do_info_qtree(Monitor *mon)
990{
991 if (main_system_bus)
992 qbus_print(mon, main_system_bus, 0);
993}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200994
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200995void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200996{
Anthony Liguori212ad112012-02-01 09:34:28 -0600997 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200998}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200999
Markus Armbruster8bc27242010-02-10 20:52:01 +01001000int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001001{
1002 QemuOpts *opts;
1003
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001004 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001005 if (!opts) {
1006 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001007 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001008 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1009 qemu_opts_del(opts);
1010 return 0;
1011 }
1012 if (!qdev_device_add(opts)) {
1013 qemu_opts_del(opts);
1014 return -1;
1015 }
1016 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001017}
1018
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001019int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001020{
1021 const char *id = qdict_get_str(qdict, "id");
1022 DeviceState *dev;
1023
1024 dev = qdev_find_recursive(main_system_bus, id);
1025 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001026 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1027 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001028 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001029 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001030}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001031
1032static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1033{
1034 int l = 0;
1035
1036 if (dev && dev->parent_bus) {
1037 char *d;
1038 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1039 if (dev->parent_bus->info->get_fw_dev_path) {
1040 d = dev->parent_bus->info->get_fw_dev_path(dev);
1041 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001042 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001043 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001044 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001045 }
1046 }
1047 l += snprintf(p + l , size - l, "/");
1048
1049 return l;
1050}
1051
1052char* qdev_get_fw_dev_path(DeviceState *dev)
1053{
1054 char path[128];
1055 int l;
1056
1057 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1058
1059 path[l-1] = '\0';
1060
1061 return strdup(path);
1062}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001063
Anthony Liguoricd34d662011-12-12 14:29:43 -06001064char *qdev_get_type(DeviceState *dev, Error **errp)
1065{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001066 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001067}
1068
Anthony Liguori85ed3032011-12-12 14:29:25 -06001069void qdev_ref(DeviceState *dev)
1070{
1071 dev->ref++;
1072}
1073
1074void qdev_unref(DeviceState *dev)
1075{
1076 g_assert(dev->ref > 0);
1077 dev->ref--;
1078}
Anthony Liguori44677de2011-12-12 14:29:26 -06001079
1080void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1081 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1082 DevicePropertyRelease *release,
1083 void *opaque, Error **errp)
1084{
1085 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1086
1087 prop->name = g_strdup(name);
1088 prop->type = g_strdup(type);
1089
1090 prop->get = get;
1091 prop->set = set;
1092 prop->release = release;
1093 prop->opaque = opaque;
1094
1095 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1096}
1097
1098static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1099{
1100 DeviceProperty *prop;
1101
1102 QTAILQ_FOREACH(prop, &dev->properties, node) {
1103 if (strcmp(prop->name, name) == 0) {
1104 return prop;
1105 }
1106 }
1107
1108 return NULL;
1109}
1110
1111void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1112 Error **errp)
1113{
1114 DeviceProperty *prop = qdev_property_find(dev, name);
1115
1116 if (prop == NULL) {
1117 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1118 return;
1119 }
1120
1121 if (!prop->get) {
1122 error_set(errp, QERR_PERMISSION_DENIED);
1123 } else {
1124 prop->get(dev, v, prop->opaque, name, errp);
1125 }
1126}
1127
1128void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1129 Error **errp)
1130{
1131 DeviceProperty *prop = qdev_property_find(dev, name);
1132
1133 if (prop == NULL) {
1134 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1135 return;
1136 }
1137
1138 if (!prop->set) {
1139 error_set(errp, QERR_PERMISSION_DENIED);
1140 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001141 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001142 }
1143}
1144
1145const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1146{
1147 DeviceProperty *prop = qdev_property_find(dev, name);
1148
1149 if (prop == NULL) {
1150 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1151 return NULL;
1152 }
1153
1154 return prop->type;
1155}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001156
1157/**
1158 * Legacy property handling
1159 */
1160
1161static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1162 const char *name, Error **errp)
1163{
1164 Property *prop = opaque;
1165
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001166 char buffer[1024];
1167 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001168
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001169 prop->info->print(dev, prop, buffer, sizeof(buffer));
1170 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001171}
1172
1173static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1174 const char *name, Error **errp)
1175{
1176 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001177 Error *local_err = NULL;
1178 char *ptr = NULL;
1179 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001180
1181 if (dev->state != DEV_STATE_CREATED) {
1182 error_set(errp, QERR_PERMISSION_DENIED);
1183 return;
1184 }
1185
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001186 visit_type_str(v, &ptr, name, &local_err);
1187 if (local_err) {
1188 error_propagate(errp, local_err);
1189 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001190 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001191
1192 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001193 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001194 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001195}
1196
1197/**
1198 * @qdev_add_legacy_property - adds a legacy property
1199 *
1200 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001201 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001202 *
1203 * Legacy properties are always processed as strings. The format of the string
1204 * depends on the property type.
1205 */
1206void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1207 Error **errp)
1208{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001209 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001210
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001211 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001212 type = g_strdup_printf("legacy<%s>",
1213 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001214
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001215 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001216 prop->info->print ? qdev_get_legacy_property : NULL,
1217 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001218 NULL,
1219 prop, errp);
1220
1221 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001222 g_free(name);
1223}
1224
1225/**
1226 * @qdev_property_add_static - add a @Property to a device.
1227 *
1228 * Static properties access data in a struct. The actual type of the
1229 * property and the field depends on the property type.
1230 */
1231void qdev_property_add_static(DeviceState *dev, Property *prop,
1232 Error **errp)
1233{
1234 qdev_property_add(dev, prop->name, prop->info->name,
1235 prop->info->get, prop->info->set,
1236 NULL,
1237 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001238}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001239
1240DeviceState *qdev_get_root(void)
1241{
1242 static DeviceState *qdev_root;
1243
1244 if (!qdev_root) {
1245 qdev_root = qdev_create(NULL, "container");
1246 qdev_init_nofail(qdev_root);
1247 }
1248
1249 return qdev_root;
1250}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001251
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001252static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1253 const char *name, Error **errp)
1254{
1255 DeviceState *child = opaque;
1256 gchar *path;
1257
1258 path = qdev_get_canonical_path(child);
1259 visit_type_str(v, &path, name, errp);
1260 g_free(path);
1261}
1262
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001263static void qdev_release_child_property(DeviceState *dev, const char *name,
1264 void *opaque)
1265{
1266 DeviceState *child = opaque;
1267
1268 qdev_unref(child);
1269}
1270
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001271void qdev_property_add_child(DeviceState *dev, const char *name,
1272 DeviceState *child, Error **errp)
1273{
1274 gchar *type;
1275
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001276 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001277
1278 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001279 NULL, qdev_release_child_property,
1280 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001281
1282 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001283 g_assert(child->parent == NULL);
1284 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001285
1286 g_free(type);
1287}
1288
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001289static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1290 const char *name, Error **errp)
1291{
1292 DeviceState **child = opaque;
1293 gchar *path;
1294
1295 if (*child) {
1296 path = qdev_get_canonical_path(*child);
1297 visit_type_str(v, &path, name, errp);
1298 g_free(path);
1299 } else {
1300 path = (gchar *)"";
1301 visit_type_str(v, &path, name, errp);
1302 }
1303}
1304
1305static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1306 const char *name, Error **errp)
1307{
1308 DeviceState **child = opaque;
1309 bool ambiguous = false;
1310 const char *type;
1311 char *path;
1312
1313 type = qdev_property_get_type(dev, name, NULL);
1314
1315 visit_type_str(v, &path, name, errp);
1316
1317 if (*child) {
1318 qdev_unref(*child);
1319 }
1320
1321 if (strcmp(path, "") != 0) {
1322 DeviceState *target;
1323
1324 target = qdev_resolve_path(path, &ambiguous);
1325 if (target) {
1326 gchar *target_type;
1327
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001328 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001329 if (strcmp(target_type, type) == 0) {
1330 *child = target;
1331 qdev_ref(target);
1332 } else {
1333 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1334 }
1335
1336 g_free(target_type);
1337 } else {
1338 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1339 }
1340 } else {
1341 *child = NULL;
1342 }
1343
1344 g_free(path);
1345}
1346
1347void qdev_property_add_link(DeviceState *dev, const char *name,
1348 const char *type, DeviceState **child,
1349 Error **errp)
1350{
1351 gchar *full_type;
1352
1353 full_type = g_strdup_printf("link<%s>", type);
1354
1355 qdev_property_add(dev, name, full_type,
1356 qdev_get_link_property,
1357 qdev_set_link_property,
1358 NULL, child, errp);
1359
1360 g_free(full_type);
1361}
1362
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001363gchar *qdev_get_canonical_path(DeviceState *dev)
1364{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001365 DeviceState *root = qdev_get_root();
1366 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001367
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001368 while (dev != root) {
1369 DeviceProperty *prop = NULL;
1370
1371 g_assert(dev->parent != NULL);
1372
1373 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1374 if (!strstart(prop->type, "child<", NULL)) {
1375 continue;
1376 }
1377
1378 if (prop->opaque == dev) {
1379 if (path) {
1380 newpath = g_strdup_printf("%s/%s", prop->name, path);
1381 g_free(path);
1382 path = newpath;
1383 } else {
1384 path = g_strdup(prop->name);
1385 }
1386 break;
1387 }
1388 }
1389
1390 g_assert(prop != NULL);
1391
1392 dev = dev->parent;
1393 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001394
1395 newpath = g_strdup_printf("/%s", path);
1396 g_free(path);
1397
1398 return newpath;
1399}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001400
1401static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1402 gchar **parts,
1403 int index)
1404{
1405 DeviceProperty *prop;
1406 DeviceState *child;
1407
1408 if (parts[index] == NULL) {
1409 return parent;
1410 }
1411
1412 if (strcmp(parts[index], "") == 0) {
1413 return qdev_resolve_abs_path(parent, parts, index + 1);
1414 }
1415
1416 prop = qdev_property_find(parent, parts[index]);
1417 if (prop == NULL) {
1418 return NULL;
1419 }
1420
1421 child = NULL;
1422 if (strstart(prop->type, "link<", NULL)) {
1423 DeviceState **pchild = prop->opaque;
1424 if (*pchild) {
1425 child = *pchild;
1426 }
1427 } else if (strstart(prop->type, "child<", NULL)) {
1428 child = prop->opaque;
1429 }
1430
1431 if (!child) {
1432 return NULL;
1433 }
1434
1435 return qdev_resolve_abs_path(child, parts, index + 1);
1436}
1437
1438static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1439 gchar **parts,
1440 bool *ambiguous)
1441{
1442 DeviceState *dev;
1443 DeviceProperty *prop;
1444
1445 dev = qdev_resolve_abs_path(parent, parts, 0);
1446
1447 QTAILQ_FOREACH(prop, &parent->properties, node) {
1448 DeviceState *found;
1449
1450 if (!strstart(prop->type, "child<", NULL)) {
1451 continue;
1452 }
1453
1454 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1455 if (found) {
1456 if (dev) {
1457 if (ambiguous) {
1458 *ambiguous = true;
1459 }
1460 return NULL;
1461 }
1462 dev = found;
1463 }
1464
1465 if (ambiguous && *ambiguous) {
1466 return NULL;
1467 }
1468 }
1469
1470 return dev;
1471}
1472
1473DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1474{
1475 bool partial_path = true;
1476 DeviceState *dev;
1477 gchar **parts;
1478
1479 parts = g_strsplit(path, "/", 0);
1480 if (parts == NULL || parts[0] == NULL) {
1481 g_strfreev(parts);
1482 return qdev_get_root();
1483 }
1484
1485 if (strcmp(parts[0], "") == 0) {
1486 partial_path = false;
1487 }
1488
1489 if (partial_path) {
1490 if (ambiguous) {
1491 *ambiguous = false;
1492 }
1493 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1494 } else {
1495 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1496 }
1497
1498 g_strfreev(parts);
1499
1500 return dev;
1501}
1502
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001503typedef struct StringProperty
1504{
1505 char *(*get)(DeviceState *, Error **);
1506 void (*set)(DeviceState *, const char *, Error **);
1507} StringProperty;
1508
1509static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1510 const char *name, Error **errp)
1511{
1512 StringProperty *prop = opaque;
1513 char *value;
1514
1515 value = prop->get(dev, errp);
1516 if (value) {
1517 visit_type_str(v, &value, name, errp);
1518 g_free(value);
1519 }
1520}
1521
1522static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1523 const char *name, Error **errp)
1524{
1525 StringProperty *prop = opaque;
1526 char *value;
1527 Error *local_err = NULL;
1528
1529 visit_type_str(v, &value, name, &local_err);
1530 if (local_err) {
1531 error_propagate(errp, local_err);
1532 return;
1533 }
1534
1535 prop->set(dev, value, errp);
1536 g_free(value);
1537}
1538
1539static void qdev_property_release_str(DeviceState *dev, const char *name,
1540 void *opaque)
1541{
1542 StringProperty *prop = opaque;
1543 g_free(prop);
1544}
1545
1546void qdev_property_add_str(DeviceState *dev, const char *name,
1547 char *(*get)(DeviceState *, Error **),
1548 void (*set)(DeviceState *, const char *, Error **),
1549 Error **errp)
1550{
1551 StringProperty *prop = g_malloc0(sizeof(*prop));
1552
1553 prop->get = get;
1554 prop->set = set;
1555
1556 qdev_property_add(dev, name, "string",
1557 get ? qdev_property_get_str : NULL,
1558 set ? qdev_property_set_str : NULL,
1559 qdev_property_release_str,
1560 prop, errp);
1561}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001562
1563void qdev_machine_init(void)
1564{
1565 qdev_get_peripheral_anon();
1566 qdev_get_peripheral();
1567}
Anthony Liguori32fea402011-12-16 14:34:46 -06001568
Anthony Liguori94afdad2011-12-04 11:36:01 -06001569void device_reset(DeviceState *dev)
1570{
1571 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1572
1573 if (klass->reset) {
1574 klass->reset(dev);
1575 }
1576}
1577
Anthony Liguori32fea402011-12-16 14:34:46 -06001578static TypeInfo device_type_info = {
1579 .name = TYPE_DEVICE,
1580 .parent = TYPE_OBJECT,
1581 .instance_size = sizeof(DeviceState),
1582 .abstract = true,
1583 .class_size = sizeof(DeviceClass),
1584};
1585
1586static void init_qdev(void)
1587{
1588 type_register_static(&device_type_info);
1589}
1590
1591device_init(init_qdev);