blob: a30a1c263d06482aedfe1167feee16dd4cc715b4 [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 Liguori30fbb9f2011-12-04 11:08:36 -060046static void qdev_subclass_init(ObjectClass *klass, void *data)
47{
48 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori6e008582011-12-09 11:06:57 -060049 DeviceInfo *info = data;
Anthony Liguori94afdad2011-12-04 11:36:01 -060050
Anthony Liguorid253e092011-12-09 11:22:58 -060051 if (info->fw_name) {
52 dc->fw_name = info->fw_name;
53 }
54 if (info->alias) {
55 dc->alias = info->alias;
56 }
57 if (info->desc) {
58 dc->desc = info->desc;
59 }
60 if (info->props) {
61 dc->props = info->props;
62 }
63 if (info->no_user) {
64 dc->no_user = info->no_user;
65 }
66 if (info->reset) {
67 dc->reset = info->reset;
68 }
69 if (info->vmsd) {
70 dc->vmsd = info->vmsd;
71 }
72 if (info->init) {
73 dc->init = info->init;
74 }
75 if (info->unplug) {
76 dc->unplug = info->unplug;
77 }
78 if (info->exit) {
79 dc->exit = info->exit;
80 }
81 if (info->bus_info) {
82 dc->bus_info = info->bus_info;
83 }
Anthony Liguori6e008582011-12-09 11:06:57 -060084 if (info->class_init) {
85 info->class_init(klass, data);
Anthony Liguori3dde52d2011-12-04 14:37:06 -060086 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060087}
88
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060089const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
90{
Anthony Liguori6e008582011-12-09 11:06:57 -060091 DeviceClass *dc = DEVICE_GET_CLASS(dev);
92 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060093}
94
95BusInfo *qdev_get_bus_info(DeviceState *dev)
96{
Anthony Liguori6e008582011-12-09 11:06:57 -060097 DeviceClass *dc = DEVICE_GET_CLASS(dev);
98 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060099}
100
101Property *qdev_get_props(DeviceState *dev)
102{
Anthony Liguori6e008582011-12-09 11:06:57 -0600103 DeviceClass *dc = DEVICE_GET_CLASS(dev);
104 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600105}
106
107const char *qdev_fw_name(DeviceState *dev)
108{
Anthony Liguori6e008582011-12-09 11:06:57 -0600109 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600110
Anthony Liguori6e008582011-12-09 11:06:57 -0600111 if (dc->fw_name) {
112 return dc->fw_name;
113 } else if (dc->alias) {
114 return dc->alias;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600115 }
116
117 return object_get_typename(OBJECT(dev));
118}
119
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600120static void qdev_do_register_subclass(DeviceInfo *info, const char *parent,
121 const char *name)
Paul Brookaae94602009-05-14 22:35:06 +0100122{
Anthony Liguori32fea402011-12-16 14:34:46 -0600123 TypeInfo type_info = {};
124
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +0200125 assert(info->size >= sizeof(DeviceState));
Paul Brookaae94602009-05-14 22:35:06 +0100126
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600127 type_info.name = name;
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600128 type_info.parent = parent;
Anthony Liguori32fea402011-12-16 14:34:46 -0600129 type_info.instance_size = info->size;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600130 type_info.class_init = qdev_subclass_init;
131 type_info.class_data = info;
Anthony Liguori32fea402011-12-16 14:34:46 -0600132
133 type_register_static(&type_info);
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600134}
Anthony Liguori32fea402011-12-16 14:34:46 -0600135
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600136void qdev_register_subclass(DeviceInfo *info, const char *parent)
137{
138 qdev_do_register_subclass(info, parent, info->name);
139 if (info->alias) {
140 qdev_do_register_subclass(info, parent, info->alias);
141 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200142}
143
Blue Swirla369da52011-09-27 19:15:42 +0000144bool qdev_exists(const char *name)
145{
Anthony Liguori212ad112012-02-01 09:34:28 -0600146 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +0000147}
Anthony Liguori40021f02011-12-04 12:22:06 -0600148
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100149static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
150 Error **errp);
151
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600152static DeviceState *qdev_create_from_info(BusState *bus, const char *typename)
Paul Brookaae94602009-05-14 22:35:06 +0100153{
Paul Brookaae94602009-05-14 22:35:06 +0100154 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600155 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100156
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600157 dev = DEVICE(object_new(typename));
Paul Brook02e2da42009-05-23 00:05:19 +0100158 dev->parent_bus = bus;
Anthony Liguori6e008582011-12-09 11:06:57 -0600159 qdev_prop_set_defaults(dev, qdev_get_props(dev));
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200160 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100161 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200162 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200163 if (qdev_hotplug) {
164 assert(bus->allow_hotplug);
165 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700166 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200167 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200168 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600169 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200170 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600171
Anthony Liguori6e008582011-12-09 11:06:57 -0600172 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600173 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100174 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600175 }
176
Anthony Liguori6e008582011-12-09 11:06:57 -0600177 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600178 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100179 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600180 }
181
Anthony Liguoricd34d662011-12-12 14:29:43 -0600182 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
183
Paul Brookaae94602009-05-14 22:35:06 +0100184 return dev;
185}
186
Markus Armbruster0c175422010-02-19 19:12:18 +0100187/* Create a new device. This only initializes the device state structure
188 and allows properties to be set. qdev_init should be called to
189 initialize the actual device emulation. */
190DeviceState *qdev_create(BusState *bus, const char *name)
191{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000192 DeviceState *dev;
193
194 dev = qdev_try_create(bus, name);
195 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100196 if (bus) {
197 hw_error("Unknown device '%s' for bus '%s'\n", name,
198 bus->info->name);
199 } else {
200 hw_error("Unknown device '%s' for default sysbus\n", name);
201 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000202 }
203
204 return dev;
205}
206
207DeviceState *qdev_try_create(BusState *bus, const char *name)
208{
Markus Armbruster0c175422010-02-19 19:12:18 +0100209 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100210 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100211 }
212
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600213 return qdev_create_from_info(bus, name);
Markus Armbruster0c175422010-02-19 19:12:18 +0100214}
215
Anthony Liguori212ad112012-02-01 09:34:28 -0600216static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200217{
Anthony Liguori212ad112012-02-01 09:34:28 -0600218 DeviceClass *dc;
219 bool *show_no_user = opaque;
220
221 dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
222
223 if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
224 return;
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200225 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600226
227 error_printf("name \"%s\"", object_class_get_name(klass));
228 if (dc->bus_info) {
229 error_printf(", bus %s", dc->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200230 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600231 if (dc->alias) {
232 error_printf(", alias \"%s\"", dc->alias);
233 }
234 if (dc->desc) {
235 error_printf(", desc \"%s\"", dc->desc);
236 }
237 if (dc->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100238 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200239 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100240 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200241}
242
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200243static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200244{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200245 DeviceState *dev = opaque;
246
247 if (strcmp(name, "driver") == 0)
248 return 0;
249 if (strcmp(name, "bus") == 0)
250 return 0;
251
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100252 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200253 return -1;
254 }
255 return 0;
256}
257
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100258int qdev_device_help(QemuOpts *opts)
259{
260 const char *driver;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100261 Property *prop;
Anthony Liguori212ad112012-02-01 09:34:28 -0600262 ObjectClass *klass;
263 DeviceClass *info;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100264
265 driver = qemu_opt_get(opts, "driver");
266 if (driver && !strcmp(driver, "?")) {
Anthony Liguori212ad112012-02-01 09:34:28 -0600267 bool show_no_user = false;
268 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100269 return 1;
270 }
271
Markus Armbruster542379f2011-11-08 11:00:38 +0100272 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100273 return 0;
274 }
275
Anthony Liguori212ad112012-02-01 09:34:28 -0600276 klass = object_class_by_name(driver);
277 if (!klass) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100278 return 0;
279 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600280 info = DEVICE_CLASS(klass);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100281
282 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100283 /*
284 * TODO Properties without a parser are just for dirty hacks.
285 * qdev_prop_ptr is the only such PropertyInfo. It's marked
286 * for removal. This conditional should be removed along with
287 * it.
288 */
289 if (!prop->info->parse) {
290 continue; /* no way to set it, don't show */
291 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600292 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100293 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100294 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200295 for (prop = info->bus_info->props; prop && prop->name; prop++) {
296 if (!prop->info->parse) {
297 continue; /* no way to set it, don't show */
298 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600299 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100300 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200301 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100302 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100303}
304
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600305static DeviceState *qdev_get_peripheral(void)
306{
307 static DeviceState *dev;
308
309 if (dev == NULL) {
310 dev = qdev_create(NULL, "container");
311 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
312 qdev_init_nofail(dev);
313 }
314
315 return dev;
316}
317
Anthony Liguori8eb02832011-12-12 14:29:37 -0600318static DeviceState *qdev_get_peripheral_anon(void)
319{
320 static DeviceState *dev;
321
322 if (dev == NULL) {
323 dev = qdev_create(NULL, "container");
324 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
325 qdev_init_nofail(dev);
326 }
327
328 return dev;
329}
330
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200331DeviceState *qdev_device_add(QemuOpts *opts)
332{
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600333 DeviceClass *k;
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200334 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200335 DeviceState *qdev;
336 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200337
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200338 driver = qemu_opt_get(opts, "driver");
339 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100340 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200341 return NULL;
342 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200343
344 /* find driver */
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600345 k = DEVICE_CLASS(object_class_by_name(driver));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200346
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200347 /* find bus */
348 path = qemu_opt_get(opts, "bus");
349 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200350 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100351 if (!bus) {
352 return NULL;
353 }
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600354 if (bus->info != k->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100355 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
356 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100357 return NULL;
358 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200359 } else {
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600360 bus = qbus_find_recursive(main_system_bus, NULL, k->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100361 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100362 qerror_report(QERR_NO_BUS_FOR_DEVICE,
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600363 driver, k->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100364 return NULL;
365 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200366 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200367 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100368 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200369 return NULL;
370 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200371
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200372 /* create device, set properties */
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600373 qdev = qdev_create_from_info(bus, driver);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200374 id = qemu_opts_id(opts);
375 if (id) {
376 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600377 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600378 } else {
379 static int anon_count;
380 gchar *name = g_strdup_printf("device[%d]", anon_count++);
381 qdev_property_add_child(qdev_get_peripheral_anon(), name,
382 qdev, NULL);
383 g_free(name);
384 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200385 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
386 qdev_free(qdev);
387 return NULL;
388 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200389 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100390 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200391 return NULL;
392 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200393 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200394 return qdev;
395}
396
Paul Brookaae94602009-05-14 22:35:06 +0100397/* Initialize a device. Device properties should be set before calling
398 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200399 calling this function.
400 On failure, destroy the device and return negative value.
401 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200402int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100403{
Anthony Liguori6e008582011-12-09 11:06:57 -0600404 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200405 int rc;
406
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200407 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600408
409 /* FIXME hopefully this doesn't break anything */
410 rc = dc->init(dev, NULL);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200411 if (rc < 0) {
412 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200413 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200414 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600415 if (qdev_get_vmsd(dev)) {
416 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200417 dev->instance_id_alias,
418 dev->alias_required_for_version);
419 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200420 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600421 if (dev->hotplugged) {
422 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200423 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200424 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100425}
426
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200427void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
428 int required_for_version)
429{
430 assert(dev->state == DEV_STATE_CREATED);
431 dev->instance_id_alias = alias_id;
432 dev->alias_required_for_version = required_for_version;
433}
434
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200435int qdev_unplug(DeviceState *dev)
436{
Anthony Liguori6e008582011-12-09 11:06:57 -0600437 DeviceClass *dc = DEVICE_GET_CLASS(dev);
438
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200439 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100440 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200441 return -1;
442 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600443 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530444
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700445 qdev_hot_removed = true;
446
Anthony Liguori6e008582011-12-09 11:06:57 -0600447 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200448}
449
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900450static int qdev_reset_one(DeviceState *dev, void *opaque)
451{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600452 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900453
454 return 0;
455}
456
457BusState *sysbus_get_default(void)
458{
Stefan Weil68694892010-12-16 19:33:22 +0100459 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900460 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100461 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900462 return main_system_bus;
463}
464
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900465static int qbus_reset_one(BusState *bus, void *opaque)
466{
467 if (bus->info->reset) {
468 return bus->info->reset(bus);
469 }
470 return 0;
471}
472
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900473void qdev_reset_all(DeviceState *dev)
474{
475 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
476}
477
Isaku Yamahata80376c32010-12-20 14:33:35 +0900478void qbus_reset_all_fn(void *opaque)
479{
480 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200481 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900482}
483
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200484/* can be used as ->unplug() callback for the simple cases */
485int qdev_simple_unplug_cb(DeviceState *dev)
486{
487 /* just zap it */
488 qdev_free(dev);
489 return 0;
490}
491
Michael Tokarev3b29a102011-04-06 17:51:59 +0400492
493/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200494 returning an error value. This is okay during machine creation.
495 Don't use for hotplug, because there callers need to recover from
496 failure. Exception: if you know the device's init() callback can't
497 fail, then qdev_init_nofail() can't fail either, and is therefore
498 usable even then. But relying on the device implementation that
499 way is somewhat unclean, and best avoided. */
500void qdev_init_nofail(DeviceState *dev)
501{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200502 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600503 error_report("Initialization of device %s failed",
504 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200505 exit(1);
506 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200507}
508
Anthony Liguori44677de2011-12-12 14:29:26 -0600509static void qdev_property_del_all(DeviceState *dev)
510{
511 while (!QTAILQ_EMPTY(&dev->properties)) {
512 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
513
514 QTAILQ_REMOVE(&dev->properties, prop, node);
515
516 if (prop->release) {
517 prop->release(dev, prop->name, prop->opaque);
518 }
519
520 g_free(prop->name);
521 g_free(prop->type);
522 g_free(prop);
523 }
524}
525
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600526static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
527{
528 DeviceProperty *prop;
529
530 QTAILQ_FOREACH(prop, &dev->properties, node) {
531 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
532 break;
533 }
534 }
535
536 g_assert(prop != NULL);
537
538 QTAILQ_REMOVE(&dev->properties, prop, node);
539
540 if (prop->release) {
541 prop->release(dev, prop->name, prop->opaque);
542 }
543
544 g_free(prop->name);
545 g_free(prop->type);
546 g_free(prop);
547}
548
Paul Brook02e2da42009-05-23 00:05:19 +0100549/* Unlink device from bus and free the structure. */
550void qdev_free(DeviceState *dev)
551{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200552 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200553 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600554 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200555
Anthony Liguori44677de2011-12-12 14:29:26 -0600556 qdev_property_del_all(dev);
557
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200558 if (dev->state == DEV_STATE_INITIALIZED) {
559 while (dev->num_child_bus) {
560 bus = QLIST_FIRST(&dev->child_bus);
561 qbus_free(bus);
562 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600563 if (qdev_get_vmsd(dev)) {
564 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
565 }
566 if (dc->exit) {
567 dc->exit(dev);
568 }
569 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200570 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600571 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200572 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200573 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600574 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200575 if (prop->info->free) {
576 prop->info->free(dev, prop);
577 }
578 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600579 if (dev->parent) {
580 qdev_property_del_child(dev->parent, dev, NULL);
581 }
582 if (dev->ref != 0) {
583 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
584 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600585 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100586}
587
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200588void qdev_machine_creation_done(void)
589{
590 /*
591 * ok, initial machine setup is done, starting from now we can
592 * only create hotpluggable devices
593 */
594 qdev_hotplug = 1;
595}
596
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700597bool qdev_machine_modified(void)
598{
599 return qdev_hot_added || qdev_hot_removed;
600}
601
Paul Brookaae94602009-05-14 22:35:06 +0100602/* Get a character (serial) device interface. */
603CharDriverState *qdev_init_chardev(DeviceState *dev)
604{
605 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530606
607 /* FIXME: This function needs to go away: use chardev properties! */
608 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100609}
610
Paul Brook02e2da42009-05-23 00:05:19 +0100611BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100612{
Paul Brook02e2da42009-05-23 00:05:19 +0100613 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100614}
615
Paul Brookaae94602009-05-14 22:35:06 +0100616void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
617{
618 assert(dev->num_gpio_in == 0);
619 dev->num_gpio_in = n;
620 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
621}
622
623void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
624{
625 assert(dev->num_gpio_out == 0);
626 dev->num_gpio_out = n;
627 dev->gpio_out = pins;
628}
629
630qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
631{
632 assert(n >= 0 && n < dev->num_gpio_in);
633 return dev->gpio_in[n];
634}
635
636void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
637{
638 assert(n >= 0 && n < dev->num_gpio_out);
639 dev->gpio_out[n] = pin;
640}
641
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200642void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
643{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200644 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200645 if (nd->vlan)
646 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
647 if (nd->netdev)
648 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530649 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200650 qdev_prop_exists(dev, "vectors")) {
651 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
652 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100653 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200654}
655
Paul Brook02e2da42009-05-23 00:05:19 +0100656BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100657{
Paul Brook02e2da42009-05-23 00:05:19 +0100658 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100659
Blue Swirl72cf2d42009-09-12 07:36:22 +0000660 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100661 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100662 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100663 }
664 }
665 return NULL;
666}
667
Anthony Liguori81699d82010-11-19 18:55:58 +0900668int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
669 qbus_walkerfn *busfn, void *opaque)
670{
671 DeviceState *dev;
672 int err;
673
674 if (busfn) {
675 err = busfn(bus, opaque);
676 if (err) {
677 return err;
678 }
679 }
680
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200681 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900682 err = qdev_walk_children(dev, devfn, busfn, opaque);
683 if (err < 0) {
684 return err;
685 }
686 }
687
688 return 0;
689}
690
691int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
692 qbus_walkerfn *busfn, void *opaque)
693{
694 BusState *bus;
695 int err;
696
697 if (devfn) {
698 err = devfn(dev, opaque);
699 if (err) {
700 return err;
701 }
702 }
703
704 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
705 err = qbus_walk_children(bus, devfn, busfn, opaque);
706 if (err < 0) {
707 return err;
708 }
709 }
710
711 return 0;
712}
713
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200714static BusState *qbus_find_recursive(BusState *bus, const char *name,
715 const BusInfo *info)
716{
717 DeviceState *dev;
718 BusState *child, *ret;
719 int match = 1;
720
721 if (name && (strcmp(bus->name, name) != 0)) {
722 match = 0;
723 }
724 if (info && (bus->info != info)) {
725 match = 0;
726 }
727 if (match) {
728 return bus;
729 }
730
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200731 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000732 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200733 ret = qbus_find_recursive(child, name, info);
734 if (ret) {
735 return ret;
736 }
737 }
738 }
739 return NULL;
740}
741
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900742DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200743{
744 DeviceState *dev, *ret;
745 BusState *child;
746
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200747 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200748 if (dev->id && strcmp(dev->id, id) == 0)
749 return dev;
750 QLIST_FOREACH(child, &dev->child_bus, sibling) {
751 ret = qdev_find_recursive(child, id);
752 if (ret) {
753 return ret;
754 }
755 }
756 }
757 return NULL;
758}
759
Markus Armbruster53db16b2010-02-18 18:55:59 +0100760static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200761{
762 BusState *child;
763 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200764
Markus Armbruster53db16b2010-02-18 18:55:59 +0100765 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600766 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000767 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100768 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200769 sep = ", ";
770 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100771 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200772}
773
Markus Armbruster53db16b2010-02-18 18:55:59 +0100774static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200775{
776 DeviceState *dev;
777 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200778
Markus Armbruster53db16b2010-02-18 18:55:59 +0100779 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200780 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600781 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200782 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100783 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200784 sep = ", ";
785 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100786 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200787}
788
789static BusState *qbus_find_bus(DeviceState *dev, char *elem)
790{
791 BusState *child;
792
Blue Swirl72cf2d42009-09-12 07:36:22 +0000793 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200794 if (strcmp(child->name, elem) == 0) {
795 return child;
796 }
797 }
798 return NULL;
799}
800
801static DeviceState *qbus_find_dev(BusState *bus, char *elem)
802{
803 DeviceState *dev;
804
805 /*
806 * try to match in order:
807 * (1) instance id, if present
808 * (2) driver name
809 * (3) driver alias, if present
810 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200811 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200812 if (dev->id && strcmp(dev->id, elem) == 0) {
813 return dev;
814 }
815 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200816 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600817 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200818 return dev;
819 }
820 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200821 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600822 DeviceClass *dc = DEVICE_GET_CLASS(dev);
823
824 if (dc->alias && strcmp(dc->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200825 return dev;
826 }
827 }
828 return NULL;
829}
830
831static BusState *qbus_find(const char *path)
832{
833 DeviceState *dev;
834 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100835 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200836 int pos, len;
837
838 /* find start element */
839 if (path[0] == '/') {
840 bus = main_system_bus;
841 pos = 0;
842 } else {
843 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100844 assert(!path[0]);
845 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200846 }
847 bus = qbus_find_recursive(main_system_bus, elem, NULL);
848 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100849 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200850 return NULL;
851 }
852 pos = len;
853 }
854
855 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100856 assert(path[pos] == '/' || !path[pos]);
857 while (path[pos] == '/') {
858 pos++;
859 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200860 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200861 return bus;
862 }
863
864 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100865 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
866 assert(0);
867 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200868 }
869 pos += len;
870 dev = qbus_find_dev(bus, elem);
871 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100872 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100873 if (!monitor_cur_is_qmp()) {
874 qbus_list_dev(bus);
875 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200876 return NULL;
877 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100878
879 assert(path[pos] == '/' || !path[pos]);
880 while (path[pos] == '/') {
881 pos++;
882 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200883 if (path[pos] == '\0') {
884 /* last specified element is a device. If it has exactly
885 * one child bus accept it nevertheless */
886 switch (dev->num_child_bus) {
887 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100888 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200889 return NULL;
890 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000891 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200892 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100893 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100894 if (!monitor_cur_is_qmp()) {
895 qbus_list_bus(dev);
896 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200897 return NULL;
898 }
899 }
900
901 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100902 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
903 assert(0);
904 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200905 }
906 pos += len;
907 bus = qbus_find_bus(dev, elem);
908 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100909 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100910 if (!monitor_cur_is_qmp()) {
911 qbus_list_bus(dev);
912 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200913 return NULL;
914 }
915 }
916}
917
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200918void qbus_create_inplace(BusState *bus, BusInfo *info,
919 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100920{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200921 char *buf;
922 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100923
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200924 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100925 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200926
927 if (name) {
928 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500929 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200930 } else if (parent && parent->id) {
931 /* parent device has id -> use it for bus name */
932 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500933 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200934 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
935 bus->name = buf;
936 } else {
937 /* no id -> use lowercase bus type for bus name */
938 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500939 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200940 len = snprintf(buf, len, "%s.%d", info->name,
941 parent ? parent->num_child_bus : 0);
942 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200943 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200944 bus->name = buf;
945 }
946
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200947 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100948 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000949 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200950 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900951 } else if (bus != main_system_bus) {
952 /* TODO: once all bus devices are qdevified,
953 only reset handler for main_system_bus should be registered here. */
954 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100955 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200956}
957
958BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
959{
960 BusState *bus;
961
Anthony Liguori7267c092011-08-20 22:09:37 -0500962 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200963 bus->qdev_allocated = 1;
964 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100965 return bus;
966}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100967
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900968static void main_system_bus_create(void)
969{
970 /* assign main_system_bus before qbus_create_inplace()
971 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500972 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900973 main_system_bus->qdev_allocated = 1;
974 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
975 "main-system-bus");
976}
977
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200978void qbus_free(BusState *bus)
979{
980 DeviceState *dev;
981
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200982 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200983 qdev_free(dev);
984 }
985 if (bus->parent) {
986 QLIST_REMOVE(bus, sibling);
987 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900988 } else {
989 assert(bus != main_system_bus); /* main_system_bus is never freed */
990 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200991 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500992 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200993 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500994 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200995 }
996}
997
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100998#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
999static void qbus_print(Monitor *mon, BusState *bus, int indent);
1000
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001001static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
1002 const char *prefix, int indent)
1003{
1004 char buf[64];
1005
1006 if (!props)
1007 return;
1008 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +01001009 /*
1010 * TODO Properties without a print method are just for dirty
1011 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1012 * marked for removal. The test props->info->print should be
1013 * removed along with it.
1014 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001015 if (props->info->print) {
1016 props->info->print(dev, props, buf, sizeof(buf));
1017 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1018 }
1019 props++;
1020 }
1021}
1022
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001023static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1024{
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001025 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001026 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +02001027 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001028 indent += 2;
1029 if (dev->num_gpio_in) {
1030 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1031 }
1032 if (dev->num_gpio_out) {
1033 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1034 }
Anthony Liguori6e008582011-12-09 11:06:57 -06001035 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001036 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001037 if (dev->parent_bus->info->print_dev)
1038 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001039 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001040 qbus_print(mon, child, indent);
1041 }
1042}
1043
1044static void qbus_print(Monitor *mon, BusState *bus, int indent)
1045{
1046 struct DeviceState *dev;
1047
1048 qdev_printf("bus: %s\n", bus->name);
1049 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001050 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001051 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001052 qdev_print(mon, dev, indent);
1053 }
1054}
1055#undef qdev_printf
1056
1057void do_info_qtree(Monitor *mon)
1058{
1059 if (main_system_bus)
1060 qbus_print(mon, main_system_bus, 0);
1061}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001062
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001063void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001064{
Anthony Liguori212ad112012-02-01 09:34:28 -06001065 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001066}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001067
Markus Armbruster8bc27242010-02-10 20:52:01 +01001068int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001069{
1070 QemuOpts *opts;
1071
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001072 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001073 if (!opts) {
1074 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001075 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001076 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1077 qemu_opts_del(opts);
1078 return 0;
1079 }
1080 if (!qdev_device_add(opts)) {
1081 qemu_opts_del(opts);
1082 return -1;
1083 }
1084 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001085}
1086
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001087int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001088{
1089 const char *id = qdict_get_str(qdict, "id");
1090 DeviceState *dev;
1091
1092 dev = qdev_find_recursive(main_system_bus, id);
1093 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001094 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1095 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001096 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001097 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001098}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001099
1100static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1101{
1102 int l = 0;
1103
1104 if (dev && dev->parent_bus) {
1105 char *d;
1106 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1107 if (dev->parent_bus->info->get_fw_dev_path) {
1108 d = dev->parent_bus->info->get_fw_dev_path(dev);
1109 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001110 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001111 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001112 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001113 }
1114 }
1115 l += snprintf(p + l , size - l, "/");
1116
1117 return l;
1118}
1119
1120char* qdev_get_fw_dev_path(DeviceState *dev)
1121{
1122 char path[128];
1123 int l;
1124
1125 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1126
1127 path[l-1] = '\0';
1128
1129 return strdup(path);
1130}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001131
Anthony Liguoricd34d662011-12-12 14:29:43 -06001132char *qdev_get_type(DeviceState *dev, Error **errp)
1133{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001134 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001135}
1136
Anthony Liguori85ed3032011-12-12 14:29:25 -06001137void qdev_ref(DeviceState *dev)
1138{
1139 dev->ref++;
1140}
1141
1142void qdev_unref(DeviceState *dev)
1143{
1144 g_assert(dev->ref > 0);
1145 dev->ref--;
1146}
Anthony Liguori44677de2011-12-12 14:29:26 -06001147
1148void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1149 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1150 DevicePropertyRelease *release,
1151 void *opaque, Error **errp)
1152{
1153 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1154
1155 prop->name = g_strdup(name);
1156 prop->type = g_strdup(type);
1157
1158 prop->get = get;
1159 prop->set = set;
1160 prop->release = release;
1161 prop->opaque = opaque;
1162
1163 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1164}
1165
1166static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1167{
1168 DeviceProperty *prop;
1169
1170 QTAILQ_FOREACH(prop, &dev->properties, node) {
1171 if (strcmp(prop->name, name) == 0) {
1172 return prop;
1173 }
1174 }
1175
1176 return NULL;
1177}
1178
1179void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1180 Error **errp)
1181{
1182 DeviceProperty *prop = qdev_property_find(dev, name);
1183
1184 if (prop == NULL) {
1185 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1186 return;
1187 }
1188
1189 if (!prop->get) {
1190 error_set(errp, QERR_PERMISSION_DENIED);
1191 } else {
1192 prop->get(dev, v, prop->opaque, name, errp);
1193 }
1194}
1195
1196void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1197 Error **errp)
1198{
1199 DeviceProperty *prop = qdev_property_find(dev, name);
1200
1201 if (prop == NULL) {
1202 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1203 return;
1204 }
1205
1206 if (!prop->set) {
1207 error_set(errp, QERR_PERMISSION_DENIED);
1208 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001209 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001210 }
1211}
1212
1213const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1214{
1215 DeviceProperty *prop = qdev_property_find(dev, name);
1216
1217 if (prop == NULL) {
1218 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1219 return NULL;
1220 }
1221
1222 return prop->type;
1223}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001224
1225/**
1226 * Legacy property handling
1227 */
1228
1229static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1230 const char *name, Error **errp)
1231{
1232 Property *prop = opaque;
1233
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001234 char buffer[1024];
1235 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001236
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001237 prop->info->print(dev, prop, buffer, sizeof(buffer));
1238 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001239}
1240
1241static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1242 const char *name, Error **errp)
1243{
1244 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001245 Error *local_err = NULL;
1246 char *ptr = NULL;
1247 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001248
1249 if (dev->state != DEV_STATE_CREATED) {
1250 error_set(errp, QERR_PERMISSION_DENIED);
1251 return;
1252 }
1253
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001254 visit_type_str(v, &ptr, name, &local_err);
1255 if (local_err) {
1256 error_propagate(errp, local_err);
1257 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001258 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001259
1260 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001261 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001262 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001263}
1264
1265/**
1266 * @qdev_add_legacy_property - adds a legacy property
1267 *
1268 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001269 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001270 *
1271 * Legacy properties are always processed as strings. The format of the string
1272 * depends on the property type.
1273 */
1274void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1275 Error **errp)
1276{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001277 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001278
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001279 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001280 type = g_strdup_printf("legacy<%s>",
1281 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001282
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001283 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001284 prop->info->print ? qdev_get_legacy_property : NULL,
1285 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001286 NULL,
1287 prop, errp);
1288
1289 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001290 g_free(name);
1291}
1292
1293/**
1294 * @qdev_property_add_static - add a @Property to a device.
1295 *
1296 * Static properties access data in a struct. The actual type of the
1297 * property and the field depends on the property type.
1298 */
1299void qdev_property_add_static(DeviceState *dev, Property *prop,
1300 Error **errp)
1301{
1302 qdev_property_add(dev, prop->name, prop->info->name,
1303 prop->info->get, prop->info->set,
1304 NULL,
1305 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001306}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001307
1308DeviceState *qdev_get_root(void)
1309{
1310 static DeviceState *qdev_root;
1311
1312 if (!qdev_root) {
1313 qdev_root = qdev_create(NULL, "container");
1314 qdev_init_nofail(qdev_root);
1315 }
1316
1317 return qdev_root;
1318}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001319
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001320static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1321 const char *name, Error **errp)
1322{
1323 DeviceState *child = opaque;
1324 gchar *path;
1325
1326 path = qdev_get_canonical_path(child);
1327 visit_type_str(v, &path, name, errp);
1328 g_free(path);
1329}
1330
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001331static void qdev_release_child_property(DeviceState *dev, const char *name,
1332 void *opaque)
1333{
1334 DeviceState *child = opaque;
1335
1336 qdev_unref(child);
1337}
1338
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001339void qdev_property_add_child(DeviceState *dev, const char *name,
1340 DeviceState *child, Error **errp)
1341{
1342 gchar *type;
1343
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001344 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001345
1346 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001347 NULL, qdev_release_child_property,
1348 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001349
1350 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001351 g_assert(child->parent == NULL);
1352 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001353
1354 g_free(type);
1355}
1356
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001357static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1358 const char *name, Error **errp)
1359{
1360 DeviceState **child = opaque;
1361 gchar *path;
1362
1363 if (*child) {
1364 path = qdev_get_canonical_path(*child);
1365 visit_type_str(v, &path, name, errp);
1366 g_free(path);
1367 } else {
1368 path = (gchar *)"";
1369 visit_type_str(v, &path, name, errp);
1370 }
1371}
1372
1373static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1374 const char *name, Error **errp)
1375{
1376 DeviceState **child = opaque;
1377 bool ambiguous = false;
1378 const char *type;
1379 char *path;
1380
1381 type = qdev_property_get_type(dev, name, NULL);
1382
1383 visit_type_str(v, &path, name, errp);
1384
1385 if (*child) {
1386 qdev_unref(*child);
1387 }
1388
1389 if (strcmp(path, "") != 0) {
1390 DeviceState *target;
1391
1392 target = qdev_resolve_path(path, &ambiguous);
1393 if (target) {
1394 gchar *target_type;
1395
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001396 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001397 if (strcmp(target_type, type) == 0) {
1398 *child = target;
1399 qdev_ref(target);
1400 } else {
1401 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1402 }
1403
1404 g_free(target_type);
1405 } else {
1406 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1407 }
1408 } else {
1409 *child = NULL;
1410 }
1411
1412 g_free(path);
1413}
1414
1415void qdev_property_add_link(DeviceState *dev, const char *name,
1416 const char *type, DeviceState **child,
1417 Error **errp)
1418{
1419 gchar *full_type;
1420
1421 full_type = g_strdup_printf("link<%s>", type);
1422
1423 qdev_property_add(dev, name, full_type,
1424 qdev_get_link_property,
1425 qdev_set_link_property,
1426 NULL, child, errp);
1427
1428 g_free(full_type);
1429}
1430
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001431gchar *qdev_get_canonical_path(DeviceState *dev)
1432{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001433 DeviceState *root = qdev_get_root();
1434 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001435
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001436 while (dev != root) {
1437 DeviceProperty *prop = NULL;
1438
1439 g_assert(dev->parent != NULL);
1440
1441 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1442 if (!strstart(prop->type, "child<", NULL)) {
1443 continue;
1444 }
1445
1446 if (prop->opaque == dev) {
1447 if (path) {
1448 newpath = g_strdup_printf("%s/%s", prop->name, path);
1449 g_free(path);
1450 path = newpath;
1451 } else {
1452 path = g_strdup(prop->name);
1453 }
1454 break;
1455 }
1456 }
1457
1458 g_assert(prop != NULL);
1459
1460 dev = dev->parent;
1461 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001462
1463 newpath = g_strdup_printf("/%s", path);
1464 g_free(path);
1465
1466 return newpath;
1467}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001468
1469static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1470 gchar **parts,
1471 int index)
1472{
1473 DeviceProperty *prop;
1474 DeviceState *child;
1475
1476 if (parts[index] == NULL) {
1477 return parent;
1478 }
1479
1480 if (strcmp(parts[index], "") == 0) {
1481 return qdev_resolve_abs_path(parent, parts, index + 1);
1482 }
1483
1484 prop = qdev_property_find(parent, parts[index]);
1485 if (prop == NULL) {
1486 return NULL;
1487 }
1488
1489 child = NULL;
1490 if (strstart(prop->type, "link<", NULL)) {
1491 DeviceState **pchild = prop->opaque;
1492 if (*pchild) {
1493 child = *pchild;
1494 }
1495 } else if (strstart(prop->type, "child<", NULL)) {
1496 child = prop->opaque;
1497 }
1498
1499 if (!child) {
1500 return NULL;
1501 }
1502
1503 return qdev_resolve_abs_path(child, parts, index + 1);
1504}
1505
1506static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1507 gchar **parts,
1508 bool *ambiguous)
1509{
1510 DeviceState *dev;
1511 DeviceProperty *prop;
1512
1513 dev = qdev_resolve_abs_path(parent, parts, 0);
1514
1515 QTAILQ_FOREACH(prop, &parent->properties, node) {
1516 DeviceState *found;
1517
1518 if (!strstart(prop->type, "child<", NULL)) {
1519 continue;
1520 }
1521
1522 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1523 if (found) {
1524 if (dev) {
1525 if (ambiguous) {
1526 *ambiguous = true;
1527 }
1528 return NULL;
1529 }
1530 dev = found;
1531 }
1532
1533 if (ambiguous && *ambiguous) {
1534 return NULL;
1535 }
1536 }
1537
1538 return dev;
1539}
1540
1541DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1542{
1543 bool partial_path = true;
1544 DeviceState *dev;
1545 gchar **parts;
1546
1547 parts = g_strsplit(path, "/", 0);
1548 if (parts == NULL || parts[0] == NULL) {
1549 g_strfreev(parts);
1550 return qdev_get_root();
1551 }
1552
1553 if (strcmp(parts[0], "") == 0) {
1554 partial_path = false;
1555 }
1556
1557 if (partial_path) {
1558 if (ambiguous) {
1559 *ambiguous = false;
1560 }
1561 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1562 } else {
1563 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1564 }
1565
1566 g_strfreev(parts);
1567
1568 return dev;
1569}
1570
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001571typedef struct StringProperty
1572{
1573 char *(*get)(DeviceState *, Error **);
1574 void (*set)(DeviceState *, const char *, Error **);
1575} StringProperty;
1576
1577static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1578 const char *name, Error **errp)
1579{
1580 StringProperty *prop = opaque;
1581 char *value;
1582
1583 value = prop->get(dev, errp);
1584 if (value) {
1585 visit_type_str(v, &value, name, errp);
1586 g_free(value);
1587 }
1588}
1589
1590static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1591 const char *name, Error **errp)
1592{
1593 StringProperty *prop = opaque;
1594 char *value;
1595 Error *local_err = NULL;
1596
1597 visit_type_str(v, &value, name, &local_err);
1598 if (local_err) {
1599 error_propagate(errp, local_err);
1600 return;
1601 }
1602
1603 prop->set(dev, value, errp);
1604 g_free(value);
1605}
1606
1607static void qdev_property_release_str(DeviceState *dev, const char *name,
1608 void *opaque)
1609{
1610 StringProperty *prop = opaque;
1611 g_free(prop);
1612}
1613
1614void qdev_property_add_str(DeviceState *dev, const char *name,
1615 char *(*get)(DeviceState *, Error **),
1616 void (*set)(DeviceState *, const char *, Error **),
1617 Error **errp)
1618{
1619 StringProperty *prop = g_malloc0(sizeof(*prop));
1620
1621 prop->get = get;
1622 prop->set = set;
1623
1624 qdev_property_add(dev, name, "string",
1625 get ? qdev_property_get_str : NULL,
1626 set ? qdev_property_set_str : NULL,
1627 qdev_property_release_str,
1628 prop, errp);
1629}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001630
1631void qdev_machine_init(void)
1632{
1633 qdev_get_peripheral_anon();
1634 qdev_get_peripheral();
1635}
Anthony Liguori32fea402011-12-16 14:34:46 -06001636
Anthony Liguori94afdad2011-12-04 11:36:01 -06001637void device_reset(DeviceState *dev)
1638{
1639 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1640
1641 if (klass->reset) {
1642 klass->reset(dev);
1643 }
1644}
1645
Anthony Liguori32fea402011-12-16 14:34:46 -06001646static TypeInfo device_type_info = {
1647 .name = TYPE_DEVICE,
1648 .parent = TYPE_OBJECT,
1649 .instance_size = sizeof(DeviceState),
1650 .abstract = true,
1651 .class_size = sizeof(DeviceClass),
1652};
1653
1654static void init_qdev(void)
1655{
1656 type_register_static(&device_type_info);
1657}
1658
1659device_init(init_qdev);