blob: e2263cb7542a5e398883fa582d99e873ed468b74 [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
Anthony Liguori6acbe4c2011-12-22 11:05:00 -060064/*
65 * Aliases were a bad idea from the start. Let's keep them
66 * from spreading further.
67 */
68typedef struct QDevAlias
69{
70 const char *typename;
71 const char *alias;
72} QDevAlias;
73
74static const QDevAlias qdev_alias_table[] = {
75 { "virtio-blk-pci", "virtio-blk" },
76 { "virtio-net-pci", "virtio-net" },
77 { "virtio-serial-pci", "virtio-serial" },
78 { "virtio-balloon-pci", "virtio-balloon" },
79 { "virtio-blk-s390", "virtio-blk" },
80 { "virtio-net-s390", "virtio-net" },
81 { "virtio-serial-s390", "virtio-serial" },
82 { "lsi53c895a", "lsi" },
83 { "ich9-ahci", "ahci" },
84 { }
85};
86
87static const char *qdev_class_get_alias(DeviceClass *dc)
88{
89 const char *typename = object_class_get_name(OBJECT_CLASS(dc));
90 int i;
91
92 for (i = 0; qdev_alias_table[i].typename; i++) {
93 if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
94 return qdev_alias_table[i].alias;
95 }
96 }
97
98 return NULL;
99}
100
101static bool qdev_class_has_alias(DeviceClass *dc)
102{
103 return (qdev_class_get_alias(dc) != NULL);
104}
105
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600106const char *qdev_fw_name(DeviceState *dev)
107{
Anthony Liguori6e008582011-12-09 11:06:57 -0600108 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600109
Anthony Liguori6e008582011-12-09 11:06:57 -0600110 if (dc->fw_name) {
111 return dc->fw_name;
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600112 } else if (qdev_class_has_alias(dc)) {
113 return qdev_class_get_alias(dc);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -0600114 }
115
116 return object_get_typename(OBJECT(dev));
117}
118
Blue Swirla369da52011-09-27 19:15:42 +0000119bool qdev_exists(const char *name)
120{
Anthony Liguori212ad112012-02-01 09:34:28 -0600121 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +0000122}
Anthony Liguori40021f02011-12-04 12:22:06 -0600123
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100124static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
125 Error **errp);
126
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600127void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
Paul Brookaae94602009-05-14 22:35:06 +0100128{
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600129 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100130
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200131 if (qdev_hotplug) {
132 assert(bus->allow_hotplug);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200133 }
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600134
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600135 dev->parent_bus = bus;
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600136 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600137
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600138 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Anthony Liguori6e008582011-12-09 11:06:57 -0600139 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600140 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100141 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600142 }
Paul Brookaae94602009-05-14 22:35:06 +0100143}
144
Markus Armbruster0c175422010-02-19 19:12:18 +0100145/* Create a new device. This only initializes the device state structure
146 and allows properties to be set. qdev_init should be called to
147 initialize the actual device emulation. */
148DeviceState *qdev_create(BusState *bus, const char *name)
149{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000150 DeviceState *dev;
151
152 dev = qdev_try_create(bus, name);
153 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100154 if (bus) {
155 hw_error("Unknown device '%s' for bus '%s'\n", name,
156 bus->info->name);
157 } else {
158 hw_error("Unknown device '%s' for default sysbus\n", name);
159 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000160 }
161
162 return dev;
163}
164
165DeviceState *qdev_try_create(BusState *bus, const char *name)
166{
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600167 DeviceState *dev;
168
169 dev = DEVICE(object_new(name));
170 if (!dev) {
171 return NULL;
172 }
173
Markus Armbruster0c175422010-02-19 19:12:18 +0100174 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100175 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100176 }
177
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600178 qdev_set_parent_bus(dev, bus);
179 qdev_prop_set_globals(dev);
180
181 return dev;
Markus Armbruster0c175422010-02-19 19:12:18 +0100182}
183
Anthony Liguori212ad112012-02-01 09:34:28 -0600184static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200185{
Anthony Liguori212ad112012-02-01 09:34:28 -0600186 DeviceClass *dc;
187 bool *show_no_user = opaque;
188
189 dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
190
191 if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
192 return;
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200193 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600194
195 error_printf("name \"%s\"", object_class_get_name(klass));
196 if (dc->bus_info) {
197 error_printf(", bus %s", dc->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200198 }
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600199 if (qdev_class_has_alias(dc)) {
200 error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
Anthony Liguori212ad112012-02-01 09:34:28 -0600201 }
202 if (dc->desc) {
203 error_printf(", desc \"%s\"", dc->desc);
204 }
205 if (dc->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100206 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200207 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100208 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200209}
210
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200211static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200212{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200213 DeviceState *dev = opaque;
214
215 if (strcmp(name, "driver") == 0)
216 return 0;
217 if (strcmp(name, "bus") == 0)
218 return 0;
219
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100220 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200221 return -1;
222 }
223 return 0;
224}
225
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600226static const char *find_typename_by_alias(const char *alias)
227{
228 int i;
229
230 for (i = 0; qdev_alias_table[i].alias; i++) {
231 if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
232 return qdev_alias_table[i].typename;
233 }
234 }
235
236 return NULL;
237}
238
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100239int qdev_device_help(QemuOpts *opts)
240{
241 const char *driver;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100242 Property *prop;
Anthony Liguori212ad112012-02-01 09:34:28 -0600243 ObjectClass *klass;
244 DeviceClass *info;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100245
246 driver = qemu_opt_get(opts, "driver");
247 if (driver && !strcmp(driver, "?")) {
Anthony Liguori212ad112012-02-01 09:34:28 -0600248 bool show_no_user = false;
249 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100250 return 1;
251 }
252
Markus Armbruster542379f2011-11-08 11:00:38 +0100253 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100254 return 0;
255 }
256
Anthony Liguori212ad112012-02-01 09:34:28 -0600257 klass = object_class_by_name(driver);
258 if (!klass) {
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600259 const char *typename = find_typename_by_alias(driver);
260
261 if (typename) {
262 driver = typename;
263 klass = object_class_by_name(driver);
264 }
265 }
266
267 if (!klass) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100268 return 0;
269 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600270 info = DEVICE_CLASS(klass);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100271
272 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100273 /*
274 * TODO Properties without a parser are just for dirty hacks.
275 * qdev_prop_ptr is the only such PropertyInfo. It's marked
276 * for removal. This conditional should be removed along with
277 * it.
278 */
279 if (!prop->info->parse) {
280 continue; /* no way to set it, don't show */
281 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600282 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100283 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100284 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200285 for (prop = info->bus_info->props; prop && prop->name; prop++) {
286 if (!prop->info->parse) {
287 continue; /* no way to set it, don't show */
288 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600289 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100290 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200291 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100292 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100293}
294
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600295static DeviceState *qdev_get_peripheral(void)
296{
297 static DeviceState *dev;
298
299 if (dev == NULL) {
300 dev = qdev_create(NULL, "container");
301 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
302 qdev_init_nofail(dev);
303 }
304
305 return dev;
306}
307
Anthony Liguori8eb02832011-12-12 14:29:37 -0600308static DeviceState *qdev_get_peripheral_anon(void)
309{
310 static DeviceState *dev;
311
312 if (dev == NULL) {
313 dev = qdev_create(NULL, "container");
314 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
315 qdev_init_nofail(dev);
316 }
317
318 return dev;
319}
320
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200321DeviceState *qdev_device_add(QemuOpts *opts)
322{
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600323 ObjectClass *obj;
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600324 DeviceClass *k;
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200325 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200326 DeviceState *qdev;
327 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200328
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200329 driver = qemu_opt_get(opts, "driver");
330 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100331 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200332 return NULL;
333 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200334
335 /* find driver */
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600336 obj = object_class_by_name(driver);
337 if (!obj) {
338 const char *typename = find_typename_by_alias(driver);
339
340 if (typename) {
341 driver = typename;
342 obj = object_class_by_name(driver);
343 }
344 }
345
346 if (!obj) {
347 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
348 return NULL;
349 }
350
351 k = DEVICE_CLASS(obj);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200352
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200353 /* find bus */
354 path = qemu_opt_get(opts, "bus");
355 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200356 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100357 if (!bus) {
358 return NULL;
359 }
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600360 if (bus->info != k->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100361 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
362 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100363 return NULL;
364 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200365 } else {
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600366 bus = qbus_find_recursive(main_system_bus, NULL, k->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100367 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100368 qerror_report(QERR_NO_BUS_FOR_DEVICE,
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600369 driver, k->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100370 return NULL;
371 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200372 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200373 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100374 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200375 return NULL;
376 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200377
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600378 if (!bus) {
379 bus = sysbus_get_default();
380 }
381
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200382 /* create device, set properties */
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600383 qdev = DEVICE(object_new(driver));
384 qdev_set_parent_bus(qdev, bus);
385 qdev_prop_set_globals(qdev);
386
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200387 id = qemu_opts_id(opts);
388 if (id) {
389 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600390 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600391 } else {
392 static int anon_count;
393 gchar *name = g_strdup_printf("device[%d]", anon_count++);
394 qdev_property_add_child(qdev_get_peripheral_anon(), name,
395 qdev, NULL);
396 g_free(name);
397 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200398 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
399 qdev_free(qdev);
400 return NULL;
401 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200402 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100403 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200404 return NULL;
405 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200406 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200407 return qdev;
408}
409
Paul Brookaae94602009-05-14 22:35:06 +0100410/* Initialize a device. Device properties should be set before calling
411 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200412 calling this function.
413 On failure, destroy the device and return negative value.
414 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200415int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100416{
Anthony Liguori6e008582011-12-09 11:06:57 -0600417 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200418 int rc;
419
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200420 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600421
Anthony Liguorid307af72011-12-09 15:02:56 -0600422 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200423 if (rc < 0) {
424 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200425 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200426 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600427 if (qdev_get_vmsd(dev)) {
428 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200429 dev->instance_id_alias,
430 dev->alias_required_for_version);
431 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200432 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600433 if (dev->hotplugged) {
434 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200435 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200436 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100437}
438
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200439void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
440 int required_for_version)
441{
442 assert(dev->state == DEV_STATE_CREATED);
443 dev->instance_id_alias = alias_id;
444 dev->alias_required_for_version = required_for_version;
445}
446
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200447int qdev_unplug(DeviceState *dev)
448{
Anthony Liguori6e008582011-12-09 11:06:57 -0600449 DeviceClass *dc = DEVICE_GET_CLASS(dev);
450
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200451 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100452 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200453 return -1;
454 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600455 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530456
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700457 qdev_hot_removed = true;
458
Anthony Liguori6e008582011-12-09 11:06:57 -0600459 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200460}
461
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900462static int qdev_reset_one(DeviceState *dev, void *opaque)
463{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600464 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900465
466 return 0;
467}
468
469BusState *sysbus_get_default(void)
470{
Stefan Weil68694892010-12-16 19:33:22 +0100471 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900472 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100473 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900474 return main_system_bus;
475}
476
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900477static int qbus_reset_one(BusState *bus, void *opaque)
478{
479 if (bus->info->reset) {
480 return bus->info->reset(bus);
481 }
482 return 0;
483}
484
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900485void qdev_reset_all(DeviceState *dev)
486{
487 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
488}
489
Isaku Yamahata80376c32010-12-20 14:33:35 +0900490void qbus_reset_all_fn(void *opaque)
491{
492 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200493 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900494}
495
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200496/* can be used as ->unplug() callback for the simple cases */
497int qdev_simple_unplug_cb(DeviceState *dev)
498{
499 /* just zap it */
500 qdev_free(dev);
501 return 0;
502}
503
Michael Tokarev3b29a102011-04-06 17:51:59 +0400504
505/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200506 returning an error value. This is okay during machine creation.
507 Don't use for hotplug, because there callers need to recover from
508 failure. Exception: if you know the device's init() callback can't
509 fail, then qdev_init_nofail() can't fail either, and is therefore
510 usable even then. But relying on the device implementation that
511 way is somewhat unclean, and best avoided. */
512void qdev_init_nofail(DeviceState *dev)
513{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200514 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600515 error_report("Initialization of device %s failed",
516 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200517 exit(1);
518 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200519}
520
Anthony Liguori44677de2011-12-12 14:29:26 -0600521static void qdev_property_del_all(DeviceState *dev)
522{
523 while (!QTAILQ_EMPTY(&dev->properties)) {
524 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
525
526 QTAILQ_REMOVE(&dev->properties, prop, node);
527
528 if (prop->release) {
529 prop->release(dev, prop->name, prop->opaque);
530 }
531
532 g_free(prop->name);
533 g_free(prop->type);
534 g_free(prop);
535 }
536}
537
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600538static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
539{
540 DeviceProperty *prop;
541
542 QTAILQ_FOREACH(prop, &dev->properties, node) {
543 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
544 break;
545 }
546 }
547
548 g_assert(prop != NULL);
549
550 QTAILQ_REMOVE(&dev->properties, prop, node);
551
552 if (prop->release) {
553 prop->release(dev, prop->name, prop->opaque);
554 }
555
556 g_free(prop->name);
557 g_free(prop->type);
558 g_free(prop);
559}
560
Paul Brook02e2da42009-05-23 00:05:19 +0100561/* Unlink device from bus and free the structure. */
562void qdev_free(DeviceState *dev)
563{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200564 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200565 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600566 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200567
Anthony Liguori44677de2011-12-12 14:29:26 -0600568 qdev_property_del_all(dev);
569
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200570 if (dev->state == DEV_STATE_INITIALIZED) {
571 while (dev->num_child_bus) {
572 bus = QLIST_FIRST(&dev->child_bus);
573 qbus_free(bus);
574 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600575 if (qdev_get_vmsd(dev)) {
576 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
577 }
578 if (dc->exit) {
579 dc->exit(dev);
580 }
581 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200582 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600583 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200584 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200585 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600586 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200587 if (prop->info->free) {
588 prop->info->free(dev, prop);
589 }
590 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600591 if (dev->parent) {
592 qdev_property_del_child(dev->parent, dev, NULL);
593 }
594 if (dev->ref != 0) {
595 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
596 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600597 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100598}
599
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200600void qdev_machine_creation_done(void)
601{
602 /*
603 * ok, initial machine setup is done, starting from now we can
604 * only create hotpluggable devices
605 */
606 qdev_hotplug = 1;
607}
608
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700609bool qdev_machine_modified(void)
610{
611 return qdev_hot_added || qdev_hot_removed;
612}
613
Paul Brookaae94602009-05-14 22:35:06 +0100614/* Get a character (serial) device interface. */
615CharDriverState *qdev_init_chardev(DeviceState *dev)
616{
617 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530618
619 /* FIXME: This function needs to go away: use chardev properties! */
620 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100621}
622
Paul Brook02e2da42009-05-23 00:05:19 +0100623BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100624{
Paul Brook02e2da42009-05-23 00:05:19 +0100625 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100626}
627
Paul Brookaae94602009-05-14 22:35:06 +0100628void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
629{
630 assert(dev->num_gpio_in == 0);
631 dev->num_gpio_in = n;
632 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
633}
634
635void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
636{
637 assert(dev->num_gpio_out == 0);
638 dev->num_gpio_out = n;
639 dev->gpio_out = pins;
640}
641
642qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
643{
644 assert(n >= 0 && n < dev->num_gpio_in);
645 return dev->gpio_in[n];
646}
647
648void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
649{
650 assert(n >= 0 && n < dev->num_gpio_out);
651 dev->gpio_out[n] = pin;
652}
653
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200654void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
655{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200656 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200657 if (nd->vlan)
658 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
659 if (nd->netdev)
660 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530661 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200662 qdev_prop_exists(dev, "vectors")) {
663 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
664 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100665 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200666}
667
Paul Brook02e2da42009-05-23 00:05:19 +0100668BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100669{
Paul Brook02e2da42009-05-23 00:05:19 +0100670 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100671
Blue Swirl72cf2d42009-09-12 07:36:22 +0000672 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100673 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100674 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100675 }
676 }
677 return NULL;
678}
679
Anthony Liguori81699d82010-11-19 18:55:58 +0900680int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
681 qbus_walkerfn *busfn, void *opaque)
682{
683 DeviceState *dev;
684 int err;
685
686 if (busfn) {
687 err = busfn(bus, opaque);
688 if (err) {
689 return err;
690 }
691 }
692
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200693 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900694 err = qdev_walk_children(dev, devfn, busfn, opaque);
695 if (err < 0) {
696 return err;
697 }
698 }
699
700 return 0;
701}
702
703int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
704 qbus_walkerfn *busfn, void *opaque)
705{
706 BusState *bus;
707 int err;
708
709 if (devfn) {
710 err = devfn(dev, opaque);
711 if (err) {
712 return err;
713 }
714 }
715
716 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
717 err = qbus_walk_children(bus, devfn, busfn, opaque);
718 if (err < 0) {
719 return err;
720 }
721 }
722
723 return 0;
724}
725
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200726static BusState *qbus_find_recursive(BusState *bus, const char *name,
727 const BusInfo *info)
728{
729 DeviceState *dev;
730 BusState *child, *ret;
731 int match = 1;
732
733 if (name && (strcmp(bus->name, name) != 0)) {
734 match = 0;
735 }
736 if (info && (bus->info != info)) {
737 match = 0;
738 }
739 if (match) {
740 return bus;
741 }
742
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200743 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000744 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200745 ret = qbus_find_recursive(child, name, info);
746 if (ret) {
747 return ret;
748 }
749 }
750 }
751 return NULL;
752}
753
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900754DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200755{
756 DeviceState *dev, *ret;
757 BusState *child;
758
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200759 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200760 if (dev->id && strcmp(dev->id, id) == 0)
761 return dev;
762 QLIST_FOREACH(child, &dev->child_bus, sibling) {
763 ret = qdev_find_recursive(child, id);
764 if (ret) {
765 return ret;
766 }
767 }
768 }
769 return NULL;
770}
771
Markus Armbruster53db16b2010-02-18 18:55:59 +0100772static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200773{
774 BusState *child;
775 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200776
Markus Armbruster53db16b2010-02-18 18:55:59 +0100777 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600778 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000779 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100780 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200781 sep = ", ";
782 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100783 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200784}
785
Markus Armbruster53db16b2010-02-18 18:55:59 +0100786static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200787{
788 DeviceState *dev;
789 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200790
Markus Armbruster53db16b2010-02-18 18:55:59 +0100791 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200792 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600793 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200794 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100795 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200796 sep = ", ";
797 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100798 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200799}
800
801static BusState *qbus_find_bus(DeviceState *dev, char *elem)
802{
803 BusState *child;
804
Blue Swirl72cf2d42009-09-12 07:36:22 +0000805 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200806 if (strcmp(child->name, elem) == 0) {
807 return child;
808 }
809 }
810 return NULL;
811}
812
813static DeviceState *qbus_find_dev(BusState *bus, char *elem)
814{
815 DeviceState *dev;
816
817 /*
818 * try to match in order:
819 * (1) instance id, if present
820 * (2) driver name
821 * (3) driver alias, if present
822 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200823 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200824 if (dev->id && strcmp(dev->id, elem) == 0) {
825 return dev;
826 }
827 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200828 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600829 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200830 return dev;
831 }
832 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200833 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600834 DeviceClass *dc = DEVICE_GET_CLASS(dev);
835
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600836 if (qdev_class_has_alias(dc) &&
837 strcmp(qdev_class_get_alias(dc), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200838 return dev;
839 }
840 }
841 return NULL;
842}
843
844static BusState *qbus_find(const char *path)
845{
846 DeviceState *dev;
847 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100848 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200849 int pos, len;
850
851 /* find start element */
852 if (path[0] == '/') {
853 bus = main_system_bus;
854 pos = 0;
855 } else {
856 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100857 assert(!path[0]);
858 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200859 }
860 bus = qbus_find_recursive(main_system_bus, elem, NULL);
861 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100862 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200863 return NULL;
864 }
865 pos = len;
866 }
867
868 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100869 assert(path[pos] == '/' || !path[pos]);
870 while (path[pos] == '/') {
871 pos++;
872 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200873 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200874 return bus;
875 }
876
877 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100878 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
879 assert(0);
880 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200881 }
882 pos += len;
883 dev = qbus_find_dev(bus, elem);
884 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100885 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100886 if (!monitor_cur_is_qmp()) {
887 qbus_list_dev(bus);
888 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200889 return NULL;
890 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100891
892 assert(path[pos] == '/' || !path[pos]);
893 while (path[pos] == '/') {
894 pos++;
895 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200896 if (path[pos] == '\0') {
897 /* last specified element is a device. If it has exactly
898 * one child bus accept it nevertheless */
899 switch (dev->num_child_bus) {
900 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100901 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200902 return NULL;
903 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000904 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200905 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100906 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100907 if (!monitor_cur_is_qmp()) {
908 qbus_list_bus(dev);
909 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200910 return NULL;
911 }
912 }
913
914 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100915 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
916 assert(0);
917 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200918 }
919 pos += len;
920 bus = qbus_find_bus(dev, elem);
921 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100922 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100923 if (!monitor_cur_is_qmp()) {
924 qbus_list_bus(dev);
925 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200926 return NULL;
927 }
928 }
929}
930
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200931void qbus_create_inplace(BusState *bus, BusInfo *info,
932 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100933{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200934 char *buf;
935 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100936
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200937 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100938 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200939
940 if (name) {
941 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500942 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200943 } else if (parent && parent->id) {
944 /* parent device has id -> use it for bus name */
945 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500946 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200947 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
948 bus->name = buf;
949 } else {
950 /* no id -> use lowercase bus type for bus name */
951 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500952 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200953 len = snprintf(buf, len, "%s.%d", info->name,
954 parent ? parent->num_child_bus : 0);
955 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200956 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200957 bus->name = buf;
958 }
959
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200960 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100961 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000962 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200963 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900964 } else if (bus != main_system_bus) {
965 /* TODO: once all bus devices are qdevified,
966 only reset handler for main_system_bus should be registered here. */
967 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100968 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200969}
970
971BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
972{
973 BusState *bus;
974
Anthony Liguori7267c092011-08-20 22:09:37 -0500975 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200976 bus->qdev_allocated = 1;
977 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100978 return bus;
979}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100980
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900981static void main_system_bus_create(void)
982{
983 /* assign main_system_bus before qbus_create_inplace()
984 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500985 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900986 main_system_bus->qdev_allocated = 1;
987 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
988 "main-system-bus");
989}
990
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200991void qbus_free(BusState *bus)
992{
993 DeviceState *dev;
994
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200995 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200996 qdev_free(dev);
997 }
998 if (bus->parent) {
999 QLIST_REMOVE(bus, sibling);
1000 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +09001001 } else {
1002 assert(bus != main_system_bus); /* main_system_bus is never freed */
1003 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001004 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001005 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001006 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001007 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001008 }
1009}
1010
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001011#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
1012static void qbus_print(Monitor *mon, BusState *bus, int indent);
1013
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001014static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
1015 const char *prefix, int indent)
1016{
1017 char buf[64];
1018
1019 if (!props)
1020 return;
1021 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +01001022 /*
1023 * TODO Properties without a print method are just for dirty
1024 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1025 * marked for removal. The test props->info->print should be
1026 * removed along with it.
1027 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001028 if (props->info->print) {
1029 props->info->print(dev, props, buf, sizeof(buf));
1030 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1031 }
1032 props++;
1033 }
1034}
1035
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001036static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1037{
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001038 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001039 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +02001040 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001041 indent += 2;
1042 if (dev->num_gpio_in) {
1043 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1044 }
1045 if (dev->num_gpio_out) {
1046 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1047 }
Anthony Liguori6e008582011-12-09 11:06:57 -06001048 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001049 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001050 if (dev->parent_bus->info->print_dev)
1051 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001052 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001053 qbus_print(mon, child, indent);
1054 }
1055}
1056
1057static void qbus_print(Monitor *mon, BusState *bus, int indent)
1058{
1059 struct DeviceState *dev;
1060
1061 qdev_printf("bus: %s\n", bus->name);
1062 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001063 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001064 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001065 qdev_print(mon, dev, indent);
1066 }
1067}
1068#undef qdev_printf
1069
1070void do_info_qtree(Monitor *mon)
1071{
1072 if (main_system_bus)
1073 qbus_print(mon, main_system_bus, 0);
1074}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001075
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001076void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001077{
Anthony Liguori212ad112012-02-01 09:34:28 -06001078 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001079}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001080
Markus Armbruster8bc27242010-02-10 20:52:01 +01001081int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001082{
1083 QemuOpts *opts;
1084
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001085 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001086 if (!opts) {
1087 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001088 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001089 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1090 qemu_opts_del(opts);
1091 return 0;
1092 }
1093 if (!qdev_device_add(opts)) {
1094 qemu_opts_del(opts);
1095 return -1;
1096 }
1097 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001098}
1099
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001100int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001101{
1102 const char *id = qdict_get_str(qdict, "id");
1103 DeviceState *dev;
1104
1105 dev = qdev_find_recursive(main_system_bus, id);
1106 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001107 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1108 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001109 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001110 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001111}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001112
1113static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1114{
1115 int l = 0;
1116
1117 if (dev && dev->parent_bus) {
1118 char *d;
1119 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1120 if (dev->parent_bus->info->get_fw_dev_path) {
1121 d = dev->parent_bus->info->get_fw_dev_path(dev);
1122 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001123 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001124 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001125 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001126 }
1127 }
1128 l += snprintf(p + l , size - l, "/");
1129
1130 return l;
1131}
1132
1133char* qdev_get_fw_dev_path(DeviceState *dev)
1134{
1135 char path[128];
1136 int l;
1137
1138 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1139
1140 path[l-1] = '\0';
1141
1142 return strdup(path);
1143}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001144
Anthony Liguoricd34d662011-12-12 14:29:43 -06001145char *qdev_get_type(DeviceState *dev, Error **errp)
1146{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001147 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001148}
1149
Anthony Liguori85ed3032011-12-12 14:29:25 -06001150void qdev_ref(DeviceState *dev)
1151{
1152 dev->ref++;
1153}
1154
1155void qdev_unref(DeviceState *dev)
1156{
1157 g_assert(dev->ref > 0);
1158 dev->ref--;
1159}
Anthony Liguori44677de2011-12-12 14:29:26 -06001160
1161void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1162 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1163 DevicePropertyRelease *release,
1164 void *opaque, Error **errp)
1165{
1166 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1167
1168 prop->name = g_strdup(name);
1169 prop->type = g_strdup(type);
1170
1171 prop->get = get;
1172 prop->set = set;
1173 prop->release = release;
1174 prop->opaque = opaque;
1175
1176 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1177}
1178
1179static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1180{
1181 DeviceProperty *prop;
1182
1183 QTAILQ_FOREACH(prop, &dev->properties, node) {
1184 if (strcmp(prop->name, name) == 0) {
1185 return prop;
1186 }
1187 }
1188
1189 return NULL;
1190}
1191
1192void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1193 Error **errp)
1194{
1195 DeviceProperty *prop = qdev_property_find(dev, name);
1196
1197 if (prop == NULL) {
1198 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1199 return;
1200 }
1201
1202 if (!prop->get) {
1203 error_set(errp, QERR_PERMISSION_DENIED);
1204 } else {
1205 prop->get(dev, v, prop->opaque, name, errp);
1206 }
1207}
1208
1209void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1210 Error **errp)
1211{
1212 DeviceProperty *prop = qdev_property_find(dev, name);
1213
1214 if (prop == NULL) {
1215 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1216 return;
1217 }
1218
1219 if (!prop->set) {
1220 error_set(errp, QERR_PERMISSION_DENIED);
1221 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001222 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001223 }
1224}
1225
1226const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1227{
1228 DeviceProperty *prop = qdev_property_find(dev, name);
1229
1230 if (prop == NULL) {
1231 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1232 return NULL;
1233 }
1234
1235 return prop->type;
1236}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001237
1238/**
1239 * Legacy property handling
1240 */
1241
1242static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1243 const char *name, Error **errp)
1244{
1245 Property *prop = opaque;
1246
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001247 char buffer[1024];
1248 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001249
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001250 prop->info->print(dev, prop, buffer, sizeof(buffer));
1251 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001252}
1253
1254static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1255 const char *name, Error **errp)
1256{
1257 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001258 Error *local_err = NULL;
1259 char *ptr = NULL;
1260 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001261
1262 if (dev->state != DEV_STATE_CREATED) {
1263 error_set(errp, QERR_PERMISSION_DENIED);
1264 return;
1265 }
1266
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001267 visit_type_str(v, &ptr, name, &local_err);
1268 if (local_err) {
1269 error_propagate(errp, local_err);
1270 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001271 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001272
1273 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001274 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001275 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001276}
1277
1278/**
1279 * @qdev_add_legacy_property - adds a legacy property
1280 *
1281 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001282 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001283 *
1284 * Legacy properties are always processed as strings. The format of the string
1285 * depends on the property type.
1286 */
1287void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1288 Error **errp)
1289{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001290 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001291
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001292 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001293 type = g_strdup_printf("legacy<%s>",
1294 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001295
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001296 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001297 prop->info->print ? qdev_get_legacy_property : NULL,
1298 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001299 NULL,
1300 prop, errp);
1301
1302 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001303 g_free(name);
1304}
1305
1306/**
1307 * @qdev_property_add_static - add a @Property to a device.
1308 *
1309 * Static properties access data in a struct. The actual type of the
1310 * property and the field depends on the property type.
1311 */
1312void qdev_property_add_static(DeviceState *dev, Property *prop,
1313 Error **errp)
1314{
1315 qdev_property_add(dev, prop->name, prop->info->name,
1316 prop->info->get, prop->info->set,
1317 NULL,
1318 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001319}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001320
1321DeviceState *qdev_get_root(void)
1322{
1323 static DeviceState *qdev_root;
1324
1325 if (!qdev_root) {
1326 qdev_root = qdev_create(NULL, "container");
1327 qdev_init_nofail(qdev_root);
1328 }
1329
1330 return qdev_root;
1331}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001332
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001333static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1334 const char *name, Error **errp)
1335{
1336 DeviceState *child = opaque;
1337 gchar *path;
1338
1339 path = qdev_get_canonical_path(child);
1340 visit_type_str(v, &path, name, errp);
1341 g_free(path);
1342}
1343
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001344static void qdev_release_child_property(DeviceState *dev, const char *name,
1345 void *opaque)
1346{
1347 DeviceState *child = opaque;
1348
1349 qdev_unref(child);
1350}
1351
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001352void qdev_property_add_child(DeviceState *dev, const char *name,
1353 DeviceState *child, Error **errp)
1354{
1355 gchar *type;
1356
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001357 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001358
1359 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001360 NULL, qdev_release_child_property,
1361 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001362
1363 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001364 g_assert(child->parent == NULL);
1365 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001366
1367 g_free(type);
1368}
1369
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001370static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1371 const char *name, Error **errp)
1372{
1373 DeviceState **child = opaque;
1374 gchar *path;
1375
1376 if (*child) {
1377 path = qdev_get_canonical_path(*child);
1378 visit_type_str(v, &path, name, errp);
1379 g_free(path);
1380 } else {
1381 path = (gchar *)"";
1382 visit_type_str(v, &path, name, errp);
1383 }
1384}
1385
1386static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1387 const char *name, Error **errp)
1388{
1389 DeviceState **child = opaque;
1390 bool ambiguous = false;
1391 const char *type;
1392 char *path;
1393
1394 type = qdev_property_get_type(dev, name, NULL);
1395
1396 visit_type_str(v, &path, name, errp);
1397
1398 if (*child) {
1399 qdev_unref(*child);
1400 }
1401
1402 if (strcmp(path, "") != 0) {
1403 DeviceState *target;
1404
1405 target = qdev_resolve_path(path, &ambiguous);
1406 if (target) {
1407 gchar *target_type;
1408
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001409 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001410 if (strcmp(target_type, type) == 0) {
1411 *child = target;
1412 qdev_ref(target);
1413 } else {
1414 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1415 }
1416
1417 g_free(target_type);
1418 } else {
1419 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1420 }
1421 } else {
1422 *child = NULL;
1423 }
1424
1425 g_free(path);
1426}
1427
1428void qdev_property_add_link(DeviceState *dev, const char *name,
1429 const char *type, DeviceState **child,
1430 Error **errp)
1431{
1432 gchar *full_type;
1433
1434 full_type = g_strdup_printf("link<%s>", type);
1435
1436 qdev_property_add(dev, name, full_type,
1437 qdev_get_link_property,
1438 qdev_set_link_property,
1439 NULL, child, errp);
1440
1441 g_free(full_type);
1442}
1443
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001444gchar *qdev_get_canonical_path(DeviceState *dev)
1445{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001446 DeviceState *root = qdev_get_root();
1447 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001448
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001449 while (dev != root) {
1450 DeviceProperty *prop = NULL;
1451
1452 g_assert(dev->parent != NULL);
1453
1454 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1455 if (!strstart(prop->type, "child<", NULL)) {
1456 continue;
1457 }
1458
1459 if (prop->opaque == dev) {
1460 if (path) {
1461 newpath = g_strdup_printf("%s/%s", prop->name, path);
1462 g_free(path);
1463 path = newpath;
1464 } else {
1465 path = g_strdup(prop->name);
1466 }
1467 break;
1468 }
1469 }
1470
1471 g_assert(prop != NULL);
1472
1473 dev = dev->parent;
1474 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001475
1476 newpath = g_strdup_printf("/%s", path);
1477 g_free(path);
1478
1479 return newpath;
1480}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001481
1482static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1483 gchar **parts,
1484 int index)
1485{
1486 DeviceProperty *prop;
1487 DeviceState *child;
1488
1489 if (parts[index] == NULL) {
1490 return parent;
1491 }
1492
1493 if (strcmp(parts[index], "") == 0) {
1494 return qdev_resolve_abs_path(parent, parts, index + 1);
1495 }
1496
1497 prop = qdev_property_find(parent, parts[index]);
1498 if (prop == NULL) {
1499 return NULL;
1500 }
1501
1502 child = NULL;
1503 if (strstart(prop->type, "link<", NULL)) {
1504 DeviceState **pchild = prop->opaque;
1505 if (*pchild) {
1506 child = *pchild;
1507 }
1508 } else if (strstart(prop->type, "child<", NULL)) {
1509 child = prop->opaque;
1510 }
1511
1512 if (!child) {
1513 return NULL;
1514 }
1515
1516 return qdev_resolve_abs_path(child, parts, index + 1);
1517}
1518
1519static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1520 gchar **parts,
1521 bool *ambiguous)
1522{
1523 DeviceState *dev;
1524 DeviceProperty *prop;
1525
1526 dev = qdev_resolve_abs_path(parent, parts, 0);
1527
1528 QTAILQ_FOREACH(prop, &parent->properties, node) {
1529 DeviceState *found;
1530
1531 if (!strstart(prop->type, "child<", NULL)) {
1532 continue;
1533 }
1534
1535 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1536 if (found) {
1537 if (dev) {
1538 if (ambiguous) {
1539 *ambiguous = true;
1540 }
1541 return NULL;
1542 }
1543 dev = found;
1544 }
1545
1546 if (ambiguous && *ambiguous) {
1547 return NULL;
1548 }
1549 }
1550
1551 return dev;
1552}
1553
1554DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1555{
1556 bool partial_path = true;
1557 DeviceState *dev;
1558 gchar **parts;
1559
1560 parts = g_strsplit(path, "/", 0);
1561 if (parts == NULL || parts[0] == NULL) {
1562 g_strfreev(parts);
1563 return qdev_get_root();
1564 }
1565
1566 if (strcmp(parts[0], "") == 0) {
1567 partial_path = false;
1568 }
1569
1570 if (partial_path) {
1571 if (ambiguous) {
1572 *ambiguous = false;
1573 }
1574 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1575 } else {
1576 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1577 }
1578
1579 g_strfreev(parts);
1580
1581 return dev;
1582}
1583
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001584typedef struct StringProperty
1585{
1586 char *(*get)(DeviceState *, Error **);
1587 void (*set)(DeviceState *, const char *, Error **);
1588} StringProperty;
1589
1590static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1591 const char *name, Error **errp)
1592{
1593 StringProperty *prop = opaque;
1594 char *value;
1595
1596 value = prop->get(dev, errp);
1597 if (value) {
1598 visit_type_str(v, &value, name, errp);
1599 g_free(value);
1600 }
1601}
1602
1603static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1604 const char *name, Error **errp)
1605{
1606 StringProperty *prop = opaque;
1607 char *value;
1608 Error *local_err = NULL;
1609
1610 visit_type_str(v, &value, name, &local_err);
1611 if (local_err) {
1612 error_propagate(errp, local_err);
1613 return;
1614 }
1615
1616 prop->set(dev, value, errp);
1617 g_free(value);
1618}
1619
1620static void qdev_property_release_str(DeviceState *dev, const char *name,
1621 void *opaque)
1622{
1623 StringProperty *prop = opaque;
1624 g_free(prop);
1625}
1626
1627void qdev_property_add_str(DeviceState *dev, const char *name,
1628 char *(*get)(DeviceState *, Error **),
1629 void (*set)(DeviceState *, const char *, Error **),
1630 Error **errp)
1631{
1632 StringProperty *prop = g_malloc0(sizeof(*prop));
1633
1634 prop->get = get;
1635 prop->set = set;
1636
1637 qdev_property_add(dev, name, "string",
1638 get ? qdev_property_get_str : NULL,
1639 set ? qdev_property_set_str : NULL,
1640 qdev_property_release_str,
1641 prop, errp);
1642}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001643
1644void qdev_machine_init(void)
1645{
1646 qdev_get_peripheral_anon();
1647 qdev_get_peripheral();
1648}
Anthony Liguori32fea402011-12-16 14:34:46 -06001649
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001650static void device_initfn(Object *obj)
1651{
1652 DeviceState *dev = DEVICE(obj);
1653 Property *prop;
1654
1655 if (qdev_hotplug) {
1656 dev->hotplugged = 1;
1657 qdev_hot_added = true;
1658 }
1659
1660 dev->instance_id_alias = -1;
1661 QTAILQ_INIT(&dev->properties);
1662 dev->state = DEV_STATE_CREATED;
1663
1664 qdev_prop_set_defaults(dev, qdev_get_props(dev));
1665 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
1666 qdev_property_add_legacy(dev, prop, NULL);
1667 qdev_property_add_static(dev, prop, NULL);
1668 }
1669
1670 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
1671}
1672
Anthony Liguori94afdad2011-12-04 11:36:01 -06001673void device_reset(DeviceState *dev)
1674{
1675 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1676
1677 if (klass->reset) {
1678 klass->reset(dev);
1679 }
1680}
1681
Anthony Liguori32fea402011-12-16 14:34:46 -06001682static TypeInfo device_type_info = {
1683 .name = TYPE_DEVICE,
1684 .parent = TYPE_OBJECT,
1685 .instance_size = sizeof(DeviceState),
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001686 .instance_init = device_initfn,
Anthony Liguori32fea402011-12-16 14:34:46 -06001687 .abstract = true,
1688 .class_size = sizeof(DeviceClass),
1689};
1690
1691static void init_qdev(void)
1692{
1693 type_register_static(&device_type_info);
1694}
1695
1696device_init(init_qdev);