blob: 9933ea210a810940f6f936bbd4040c4f1e3c16aa [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 Liguori18b6dad2011-12-09 12:08:01 -0600127static DeviceState *qdev_create_from_info(BusState *bus, const char *typename)
Paul Brookaae94602009-05-14 22:35:06 +0100128{
Paul Brookaae94602009-05-14 22:35:06 +0100129 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600130 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100131
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600132 dev = DEVICE(object_new(typename));
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600133
Paul Brook02e2da42009-05-23 00:05:19 +0100134 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200135 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600136
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200137 if (qdev_hotplug) {
138 assert(bus->allow_hotplug);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200139 }
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600140
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600141 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600142
Anthony Liguori6e008582011-12-09 11:06:57 -0600143 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600144 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100145 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600146 }
147
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600148 qdev_prop_set_globals(dev);
Anthony Liguoricd34d662011-12-12 14:29:43 -0600149
Paul Brookaae94602009-05-14 22:35:06 +0100150 return dev;
151}
152
Markus Armbruster0c175422010-02-19 19:12:18 +0100153/* Create a new device. This only initializes the device state structure
154 and allows properties to be set. qdev_init should be called to
155 initialize the actual device emulation. */
156DeviceState *qdev_create(BusState *bus, const char *name)
157{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000158 DeviceState *dev;
159
160 dev = qdev_try_create(bus, name);
161 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100162 if (bus) {
163 hw_error("Unknown device '%s' for bus '%s'\n", name,
164 bus->info->name);
165 } else {
166 hw_error("Unknown device '%s' for default sysbus\n", name);
167 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000168 }
169
170 return dev;
171}
172
173DeviceState *qdev_try_create(BusState *bus, const char *name)
174{
Markus Armbruster0c175422010-02-19 19:12:18 +0100175 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100176 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100177 }
178
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600179 return qdev_create_from_info(bus, name);
Markus Armbruster0c175422010-02-19 19:12:18 +0100180}
181
Anthony Liguori212ad112012-02-01 09:34:28 -0600182static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200183{
Anthony Liguori212ad112012-02-01 09:34:28 -0600184 DeviceClass *dc;
185 bool *show_no_user = opaque;
186
187 dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
188
189 if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
190 return;
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200191 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600192
193 error_printf("name \"%s\"", object_class_get_name(klass));
194 if (dc->bus_info) {
195 error_printf(", bus %s", dc->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200196 }
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600197 if (qdev_class_has_alias(dc)) {
198 error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
Anthony Liguori212ad112012-02-01 09:34:28 -0600199 }
200 if (dc->desc) {
201 error_printf(", desc \"%s\"", dc->desc);
202 }
203 if (dc->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100204 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200205 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100206 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200207}
208
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200209static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200210{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200211 DeviceState *dev = opaque;
212
213 if (strcmp(name, "driver") == 0)
214 return 0;
215 if (strcmp(name, "bus") == 0)
216 return 0;
217
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100218 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200219 return -1;
220 }
221 return 0;
222}
223
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600224static const char *find_typename_by_alias(const char *alias)
225{
226 int i;
227
228 for (i = 0; qdev_alias_table[i].alias; i++) {
229 if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
230 return qdev_alias_table[i].typename;
231 }
232 }
233
234 return NULL;
235}
236
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100237int qdev_device_help(QemuOpts *opts)
238{
239 const char *driver;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100240 Property *prop;
Anthony Liguori212ad112012-02-01 09:34:28 -0600241 ObjectClass *klass;
242 DeviceClass *info;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100243
244 driver = qemu_opt_get(opts, "driver");
245 if (driver && !strcmp(driver, "?")) {
Anthony Liguori212ad112012-02-01 09:34:28 -0600246 bool show_no_user = false;
247 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100248 return 1;
249 }
250
Markus Armbruster542379f2011-11-08 11:00:38 +0100251 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100252 return 0;
253 }
254
Anthony Liguori212ad112012-02-01 09:34:28 -0600255 klass = object_class_by_name(driver);
256 if (!klass) {
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600257 const char *typename = find_typename_by_alias(driver);
258
259 if (typename) {
260 driver = typename;
261 klass = object_class_by_name(driver);
262 }
263 }
264
265 if (!klass) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100266 return 0;
267 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600268 info = DEVICE_CLASS(klass);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100269
270 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100271 /*
272 * TODO Properties without a parser are just for dirty hacks.
273 * qdev_prop_ptr is the only such PropertyInfo. It's marked
274 * for removal. This conditional should be removed along with
275 * it.
276 */
277 if (!prop->info->parse) {
278 continue; /* no way to set it, don't show */
279 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600280 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100281 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100282 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200283 for (prop = info->bus_info->props; prop && prop->name; prop++) {
284 if (!prop->info->parse) {
285 continue; /* no way to set it, don't show */
286 }
Anthony Liguori212ad112012-02-01 09:34:28 -0600287 error_printf("%s.%s=%s\n", driver, prop->name,
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100288 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200289 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100290 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100291}
292
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600293static DeviceState *qdev_get_peripheral(void)
294{
295 static DeviceState *dev;
296
297 if (dev == NULL) {
298 dev = qdev_create(NULL, "container");
299 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
300 qdev_init_nofail(dev);
301 }
302
303 return dev;
304}
305
Anthony Liguori8eb02832011-12-12 14:29:37 -0600306static DeviceState *qdev_get_peripheral_anon(void)
307{
308 static DeviceState *dev;
309
310 if (dev == NULL) {
311 dev = qdev_create(NULL, "container");
312 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
313 qdev_init_nofail(dev);
314 }
315
316 return dev;
317}
318
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200319DeviceState *qdev_device_add(QemuOpts *opts)
320{
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600321 ObjectClass *obj;
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600322 DeviceClass *k;
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200323 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200324 DeviceState *qdev;
325 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200326
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200327 driver = qemu_opt_get(opts, "driver");
328 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100329 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200330 return NULL;
331 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200332
333 /* find driver */
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600334 obj = object_class_by_name(driver);
335 if (!obj) {
336 const char *typename = find_typename_by_alias(driver);
337
338 if (typename) {
339 driver = typename;
340 obj = object_class_by_name(driver);
341 }
342 }
343
344 if (!obj) {
345 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
346 return NULL;
347 }
348
349 k = DEVICE_CLASS(obj);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200350
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200351 /* find bus */
352 path = qemu_opt_get(opts, "bus");
353 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200354 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100355 if (!bus) {
356 return NULL;
357 }
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600358 if (bus->info != k->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100359 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
360 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100361 return NULL;
362 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200363 } else {
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600364 bus = qbus_find_recursive(main_system_bus, NULL, k->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100365 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100366 qerror_report(QERR_NO_BUS_FOR_DEVICE,
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600367 driver, k->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100368 return NULL;
369 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200370 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200371 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100372 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200373 return NULL;
374 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200375
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200376 /* create device, set properties */
Anthony Liguori18b6dad2011-12-09 12:08:01 -0600377 qdev = qdev_create_from_info(bus, driver);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200378 id = qemu_opts_id(opts);
379 if (id) {
380 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600381 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600382 } else {
383 static int anon_count;
384 gchar *name = g_strdup_printf("device[%d]", anon_count++);
385 qdev_property_add_child(qdev_get_peripheral_anon(), name,
386 qdev, NULL);
387 g_free(name);
388 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200389 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
390 qdev_free(qdev);
391 return NULL;
392 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200393 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100394 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200395 return NULL;
396 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200397 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200398 return qdev;
399}
400
Paul Brookaae94602009-05-14 22:35:06 +0100401/* Initialize a device. Device properties should be set before calling
402 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200403 calling this function.
404 On failure, destroy the device and return negative value.
405 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200406int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100407{
Anthony Liguori6e008582011-12-09 11:06:57 -0600408 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200409 int rc;
410
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200411 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600412
Anthony Liguorid307af72011-12-09 15:02:56 -0600413 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200414 if (rc < 0) {
415 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200416 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200417 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600418 if (qdev_get_vmsd(dev)) {
419 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200420 dev->instance_id_alias,
421 dev->alias_required_for_version);
422 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200423 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600424 if (dev->hotplugged) {
425 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200426 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200427 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100428}
429
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200430void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
431 int required_for_version)
432{
433 assert(dev->state == DEV_STATE_CREATED);
434 dev->instance_id_alias = alias_id;
435 dev->alias_required_for_version = required_for_version;
436}
437
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200438int qdev_unplug(DeviceState *dev)
439{
Anthony Liguori6e008582011-12-09 11:06:57 -0600440 DeviceClass *dc = DEVICE_GET_CLASS(dev);
441
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200442 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100443 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200444 return -1;
445 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600446 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530447
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700448 qdev_hot_removed = true;
449
Anthony Liguori6e008582011-12-09 11:06:57 -0600450 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200451}
452
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900453static int qdev_reset_one(DeviceState *dev, void *opaque)
454{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600455 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900456
457 return 0;
458}
459
460BusState *sysbus_get_default(void)
461{
Stefan Weil68694892010-12-16 19:33:22 +0100462 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900463 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100464 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900465 return main_system_bus;
466}
467
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900468static int qbus_reset_one(BusState *bus, void *opaque)
469{
470 if (bus->info->reset) {
471 return bus->info->reset(bus);
472 }
473 return 0;
474}
475
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900476void qdev_reset_all(DeviceState *dev)
477{
478 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
479}
480
Isaku Yamahata80376c32010-12-20 14:33:35 +0900481void qbus_reset_all_fn(void *opaque)
482{
483 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200484 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900485}
486
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200487/* can be used as ->unplug() callback for the simple cases */
488int qdev_simple_unplug_cb(DeviceState *dev)
489{
490 /* just zap it */
491 qdev_free(dev);
492 return 0;
493}
494
Michael Tokarev3b29a102011-04-06 17:51:59 +0400495
496/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200497 returning an error value. This is okay during machine creation.
498 Don't use for hotplug, because there callers need to recover from
499 failure. Exception: if you know the device's init() callback can't
500 fail, then qdev_init_nofail() can't fail either, and is therefore
501 usable even then. But relying on the device implementation that
502 way is somewhat unclean, and best avoided. */
503void qdev_init_nofail(DeviceState *dev)
504{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200505 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600506 error_report("Initialization of device %s failed",
507 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200508 exit(1);
509 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200510}
511
Anthony Liguori44677de2011-12-12 14:29:26 -0600512static void qdev_property_del_all(DeviceState *dev)
513{
514 while (!QTAILQ_EMPTY(&dev->properties)) {
515 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
516
517 QTAILQ_REMOVE(&dev->properties, prop, node);
518
519 if (prop->release) {
520 prop->release(dev, prop->name, prop->opaque);
521 }
522
523 g_free(prop->name);
524 g_free(prop->type);
525 g_free(prop);
526 }
527}
528
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600529static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
530{
531 DeviceProperty *prop;
532
533 QTAILQ_FOREACH(prop, &dev->properties, node) {
534 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
535 break;
536 }
537 }
538
539 g_assert(prop != NULL);
540
541 QTAILQ_REMOVE(&dev->properties, prop, node);
542
543 if (prop->release) {
544 prop->release(dev, prop->name, prop->opaque);
545 }
546
547 g_free(prop->name);
548 g_free(prop->type);
549 g_free(prop);
550}
551
Paul Brook02e2da42009-05-23 00:05:19 +0100552/* Unlink device from bus and free the structure. */
553void qdev_free(DeviceState *dev)
554{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200555 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200556 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600557 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200558
Anthony Liguori44677de2011-12-12 14:29:26 -0600559 qdev_property_del_all(dev);
560
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200561 if (dev->state == DEV_STATE_INITIALIZED) {
562 while (dev->num_child_bus) {
563 bus = QLIST_FIRST(&dev->child_bus);
564 qbus_free(bus);
565 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600566 if (qdev_get_vmsd(dev)) {
567 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
568 }
569 if (dc->exit) {
570 dc->exit(dev);
571 }
572 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200573 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600574 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200575 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200576 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600577 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200578 if (prop->info->free) {
579 prop->info->free(dev, prop);
580 }
581 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600582 if (dev->parent) {
583 qdev_property_del_child(dev->parent, dev, NULL);
584 }
585 if (dev->ref != 0) {
586 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
587 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600588 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100589}
590
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200591void qdev_machine_creation_done(void)
592{
593 /*
594 * ok, initial machine setup is done, starting from now we can
595 * only create hotpluggable devices
596 */
597 qdev_hotplug = 1;
598}
599
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700600bool qdev_machine_modified(void)
601{
602 return qdev_hot_added || qdev_hot_removed;
603}
604
Paul Brookaae94602009-05-14 22:35:06 +0100605/* Get a character (serial) device interface. */
606CharDriverState *qdev_init_chardev(DeviceState *dev)
607{
608 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530609
610 /* FIXME: This function needs to go away: use chardev properties! */
611 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100612}
613
Paul Brook02e2da42009-05-23 00:05:19 +0100614BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100615{
Paul Brook02e2da42009-05-23 00:05:19 +0100616 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100617}
618
Paul Brookaae94602009-05-14 22:35:06 +0100619void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
620{
621 assert(dev->num_gpio_in == 0);
622 dev->num_gpio_in = n;
623 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
624}
625
626void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
627{
628 assert(dev->num_gpio_out == 0);
629 dev->num_gpio_out = n;
630 dev->gpio_out = pins;
631}
632
633qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
634{
635 assert(n >= 0 && n < dev->num_gpio_in);
636 return dev->gpio_in[n];
637}
638
639void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
640{
641 assert(n >= 0 && n < dev->num_gpio_out);
642 dev->gpio_out[n] = pin;
643}
644
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200645void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
646{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200647 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200648 if (nd->vlan)
649 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
650 if (nd->netdev)
651 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530652 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200653 qdev_prop_exists(dev, "vectors")) {
654 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
655 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100656 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200657}
658
Paul Brook02e2da42009-05-23 00:05:19 +0100659BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100660{
Paul Brook02e2da42009-05-23 00:05:19 +0100661 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100662
Blue Swirl72cf2d42009-09-12 07:36:22 +0000663 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100664 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100665 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100666 }
667 }
668 return NULL;
669}
670
Anthony Liguori81699d82010-11-19 18:55:58 +0900671int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
672 qbus_walkerfn *busfn, void *opaque)
673{
674 DeviceState *dev;
675 int err;
676
677 if (busfn) {
678 err = busfn(bus, opaque);
679 if (err) {
680 return err;
681 }
682 }
683
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200684 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900685 err = qdev_walk_children(dev, devfn, busfn, opaque);
686 if (err < 0) {
687 return err;
688 }
689 }
690
691 return 0;
692}
693
694int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
695 qbus_walkerfn *busfn, void *opaque)
696{
697 BusState *bus;
698 int err;
699
700 if (devfn) {
701 err = devfn(dev, opaque);
702 if (err) {
703 return err;
704 }
705 }
706
707 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
708 err = qbus_walk_children(bus, devfn, busfn, opaque);
709 if (err < 0) {
710 return err;
711 }
712 }
713
714 return 0;
715}
716
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200717static BusState *qbus_find_recursive(BusState *bus, const char *name,
718 const BusInfo *info)
719{
720 DeviceState *dev;
721 BusState *child, *ret;
722 int match = 1;
723
724 if (name && (strcmp(bus->name, name) != 0)) {
725 match = 0;
726 }
727 if (info && (bus->info != info)) {
728 match = 0;
729 }
730 if (match) {
731 return bus;
732 }
733
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200734 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000735 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200736 ret = qbus_find_recursive(child, name, info);
737 if (ret) {
738 return ret;
739 }
740 }
741 }
742 return NULL;
743}
744
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900745DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200746{
747 DeviceState *dev, *ret;
748 BusState *child;
749
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200750 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200751 if (dev->id && strcmp(dev->id, id) == 0)
752 return dev;
753 QLIST_FOREACH(child, &dev->child_bus, sibling) {
754 ret = qdev_find_recursive(child, id);
755 if (ret) {
756 return ret;
757 }
758 }
759 }
760 return NULL;
761}
762
Markus Armbruster53db16b2010-02-18 18:55:59 +0100763static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200764{
765 BusState *child;
766 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200767
Markus Armbruster53db16b2010-02-18 18:55:59 +0100768 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600769 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000770 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100771 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200772 sep = ", ";
773 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100774 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200775}
776
Markus Armbruster53db16b2010-02-18 18:55:59 +0100777static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200778{
779 DeviceState *dev;
780 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200781
Markus Armbruster53db16b2010-02-18 18:55:59 +0100782 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200783 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600784 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200785 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100786 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200787 sep = ", ";
788 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100789 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200790}
791
792static BusState *qbus_find_bus(DeviceState *dev, char *elem)
793{
794 BusState *child;
795
Blue Swirl72cf2d42009-09-12 07:36:22 +0000796 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200797 if (strcmp(child->name, elem) == 0) {
798 return child;
799 }
800 }
801 return NULL;
802}
803
804static DeviceState *qbus_find_dev(BusState *bus, char *elem)
805{
806 DeviceState *dev;
807
808 /*
809 * try to match in order:
810 * (1) instance id, if present
811 * (2) driver name
812 * (3) driver alias, if present
813 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200814 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200815 if (dev->id && strcmp(dev->id, elem) == 0) {
816 return dev;
817 }
818 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200819 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600820 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200821 return dev;
822 }
823 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200824 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600825 DeviceClass *dc = DEVICE_GET_CLASS(dev);
826
Anthony Liguori6acbe4c2011-12-22 11:05:00 -0600827 if (qdev_class_has_alias(dc) &&
828 strcmp(qdev_class_get_alias(dc), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200829 return dev;
830 }
831 }
832 return NULL;
833}
834
835static BusState *qbus_find(const char *path)
836{
837 DeviceState *dev;
838 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100839 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200840 int pos, len;
841
842 /* find start element */
843 if (path[0] == '/') {
844 bus = main_system_bus;
845 pos = 0;
846 } else {
847 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100848 assert(!path[0]);
849 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200850 }
851 bus = qbus_find_recursive(main_system_bus, elem, NULL);
852 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100853 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200854 return NULL;
855 }
856 pos = len;
857 }
858
859 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100860 assert(path[pos] == '/' || !path[pos]);
861 while (path[pos] == '/') {
862 pos++;
863 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200864 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200865 return bus;
866 }
867
868 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100869 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
870 assert(0);
871 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200872 }
873 pos += len;
874 dev = qbus_find_dev(bus, elem);
875 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100876 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100877 if (!monitor_cur_is_qmp()) {
878 qbus_list_dev(bus);
879 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200880 return NULL;
881 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100882
883 assert(path[pos] == '/' || !path[pos]);
884 while (path[pos] == '/') {
885 pos++;
886 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200887 if (path[pos] == '\0') {
888 /* last specified element is a device. If it has exactly
889 * one child bus accept it nevertheless */
890 switch (dev->num_child_bus) {
891 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100892 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200893 return NULL;
894 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000895 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200896 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100897 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100898 if (!monitor_cur_is_qmp()) {
899 qbus_list_bus(dev);
900 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200901 return NULL;
902 }
903 }
904
905 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100906 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
907 assert(0);
908 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200909 }
910 pos += len;
911 bus = qbus_find_bus(dev, elem);
912 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100913 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100914 if (!monitor_cur_is_qmp()) {
915 qbus_list_bus(dev);
916 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200917 return NULL;
918 }
919 }
920}
921
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200922void qbus_create_inplace(BusState *bus, BusInfo *info,
923 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100924{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200925 char *buf;
926 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100927
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200928 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100929 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200930
931 if (name) {
932 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500933 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200934 } else if (parent && parent->id) {
935 /* parent device has id -> use it for bus name */
936 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500937 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200938 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
939 bus->name = buf;
940 } else {
941 /* no id -> use lowercase bus type for bus name */
942 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500943 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200944 len = snprintf(buf, len, "%s.%d", info->name,
945 parent ? parent->num_child_bus : 0);
946 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200947 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200948 bus->name = buf;
949 }
950
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200951 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100952 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000953 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200954 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900955 } else if (bus != main_system_bus) {
956 /* TODO: once all bus devices are qdevified,
957 only reset handler for main_system_bus should be registered here. */
958 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100959 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200960}
961
962BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
963{
964 BusState *bus;
965
Anthony Liguori7267c092011-08-20 22:09:37 -0500966 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200967 bus->qdev_allocated = 1;
968 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100969 return bus;
970}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100971
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900972static void main_system_bus_create(void)
973{
974 /* assign main_system_bus before qbus_create_inplace()
975 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500976 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900977 main_system_bus->qdev_allocated = 1;
978 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
979 "main-system-bus");
980}
981
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200982void qbus_free(BusState *bus)
983{
984 DeviceState *dev;
985
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200986 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200987 qdev_free(dev);
988 }
989 if (bus->parent) {
990 QLIST_REMOVE(bus, sibling);
991 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900992 } else {
993 assert(bus != main_system_bus); /* main_system_bus is never freed */
994 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200995 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500996 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200997 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500998 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200999 }
1000}
1001
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001002#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
1003static void qbus_print(Monitor *mon, BusState *bus, int indent);
1004
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001005static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
1006 const char *prefix, int indent)
1007{
1008 char buf[64];
1009
1010 if (!props)
1011 return;
1012 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +01001013 /*
1014 * TODO Properties without a print method are just for dirty
1015 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1016 * marked for removal. The test props->info->print should be
1017 * removed along with it.
1018 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001019 if (props->info->print) {
1020 props->info->print(dev, props, buf, sizeof(buf));
1021 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1022 }
1023 props++;
1024 }
1025}
1026
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001027static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1028{
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001029 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001030 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +02001031 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001032 indent += 2;
1033 if (dev->num_gpio_in) {
1034 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1035 }
1036 if (dev->num_gpio_out) {
1037 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1038 }
Anthony Liguori6e008582011-12-09 11:06:57 -06001039 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001040 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001041 if (dev->parent_bus->info->print_dev)
1042 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001043 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001044 qbus_print(mon, child, indent);
1045 }
1046}
1047
1048static void qbus_print(Monitor *mon, BusState *bus, int indent)
1049{
1050 struct DeviceState *dev;
1051
1052 qdev_printf("bus: %s\n", bus->name);
1053 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001054 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001055 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001056 qdev_print(mon, dev, indent);
1057 }
1058}
1059#undef qdev_printf
1060
1061void do_info_qtree(Monitor *mon)
1062{
1063 if (main_system_bus)
1064 qbus_print(mon, main_system_bus, 0);
1065}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001066
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001067void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001068{
Anthony Liguori212ad112012-02-01 09:34:28 -06001069 object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001070}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001071
Markus Armbruster8bc27242010-02-10 20:52:01 +01001072int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001073{
1074 QemuOpts *opts;
1075
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001076 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001077 if (!opts) {
1078 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001079 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001080 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1081 qemu_opts_del(opts);
1082 return 0;
1083 }
1084 if (!qdev_device_add(opts)) {
1085 qemu_opts_del(opts);
1086 return -1;
1087 }
1088 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001089}
1090
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001091int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001092{
1093 const char *id = qdict_get_str(qdict, "id");
1094 DeviceState *dev;
1095
1096 dev = qdev_find_recursive(main_system_bus, id);
1097 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001098 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1099 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001100 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001101 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001102}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001103
1104static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1105{
1106 int l = 0;
1107
1108 if (dev && dev->parent_bus) {
1109 char *d;
1110 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1111 if (dev->parent_bus->info->get_fw_dev_path) {
1112 d = dev->parent_bus->info->get_fw_dev_path(dev);
1113 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001114 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001115 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001116 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001117 }
1118 }
1119 l += snprintf(p + l , size - l, "/");
1120
1121 return l;
1122}
1123
1124char* qdev_get_fw_dev_path(DeviceState *dev)
1125{
1126 char path[128];
1127 int l;
1128
1129 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1130
1131 path[l-1] = '\0';
1132
1133 return strdup(path);
1134}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001135
Anthony Liguoricd34d662011-12-12 14:29:43 -06001136char *qdev_get_type(DeviceState *dev, Error **errp)
1137{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001138 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001139}
1140
Anthony Liguori85ed3032011-12-12 14:29:25 -06001141void qdev_ref(DeviceState *dev)
1142{
1143 dev->ref++;
1144}
1145
1146void qdev_unref(DeviceState *dev)
1147{
1148 g_assert(dev->ref > 0);
1149 dev->ref--;
1150}
Anthony Liguori44677de2011-12-12 14:29:26 -06001151
1152void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1153 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1154 DevicePropertyRelease *release,
1155 void *opaque, Error **errp)
1156{
1157 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1158
1159 prop->name = g_strdup(name);
1160 prop->type = g_strdup(type);
1161
1162 prop->get = get;
1163 prop->set = set;
1164 prop->release = release;
1165 prop->opaque = opaque;
1166
1167 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1168}
1169
1170static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1171{
1172 DeviceProperty *prop;
1173
1174 QTAILQ_FOREACH(prop, &dev->properties, node) {
1175 if (strcmp(prop->name, name) == 0) {
1176 return prop;
1177 }
1178 }
1179
1180 return NULL;
1181}
1182
1183void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1184 Error **errp)
1185{
1186 DeviceProperty *prop = qdev_property_find(dev, name);
1187
1188 if (prop == NULL) {
1189 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1190 return;
1191 }
1192
1193 if (!prop->get) {
1194 error_set(errp, QERR_PERMISSION_DENIED);
1195 } else {
1196 prop->get(dev, v, prop->opaque, name, errp);
1197 }
1198}
1199
1200void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1201 Error **errp)
1202{
1203 DeviceProperty *prop = qdev_property_find(dev, name);
1204
1205 if (prop == NULL) {
1206 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1207 return;
1208 }
1209
1210 if (!prop->set) {
1211 error_set(errp, QERR_PERMISSION_DENIED);
1212 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001213 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001214 }
1215}
1216
1217const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1218{
1219 DeviceProperty *prop = qdev_property_find(dev, name);
1220
1221 if (prop == NULL) {
1222 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1223 return NULL;
1224 }
1225
1226 return prop->type;
1227}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001228
1229/**
1230 * Legacy property handling
1231 */
1232
1233static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1234 const char *name, Error **errp)
1235{
1236 Property *prop = opaque;
1237
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001238 char buffer[1024];
1239 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001240
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001241 prop->info->print(dev, prop, buffer, sizeof(buffer));
1242 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001243}
1244
1245static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1246 const char *name, Error **errp)
1247{
1248 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001249 Error *local_err = NULL;
1250 char *ptr = NULL;
1251 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001252
1253 if (dev->state != DEV_STATE_CREATED) {
1254 error_set(errp, QERR_PERMISSION_DENIED);
1255 return;
1256 }
1257
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001258 visit_type_str(v, &ptr, name, &local_err);
1259 if (local_err) {
1260 error_propagate(errp, local_err);
1261 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001262 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001263
1264 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001265 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001266 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001267}
1268
1269/**
1270 * @qdev_add_legacy_property - adds a legacy property
1271 *
1272 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001273 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001274 *
1275 * Legacy properties are always processed as strings. The format of the string
1276 * depends on the property type.
1277 */
1278void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1279 Error **errp)
1280{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001281 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001282
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001283 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001284 type = g_strdup_printf("legacy<%s>",
1285 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001286
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001287 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001288 prop->info->print ? qdev_get_legacy_property : NULL,
1289 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001290 NULL,
1291 prop, errp);
1292
1293 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001294 g_free(name);
1295}
1296
1297/**
1298 * @qdev_property_add_static - add a @Property to a device.
1299 *
1300 * Static properties access data in a struct. The actual type of the
1301 * property and the field depends on the property type.
1302 */
1303void qdev_property_add_static(DeviceState *dev, Property *prop,
1304 Error **errp)
1305{
1306 qdev_property_add(dev, prop->name, prop->info->name,
1307 prop->info->get, prop->info->set,
1308 NULL,
1309 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001310}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001311
1312DeviceState *qdev_get_root(void)
1313{
1314 static DeviceState *qdev_root;
1315
1316 if (!qdev_root) {
1317 qdev_root = qdev_create(NULL, "container");
1318 qdev_init_nofail(qdev_root);
1319 }
1320
1321 return qdev_root;
1322}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001323
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001324static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1325 const char *name, Error **errp)
1326{
1327 DeviceState *child = opaque;
1328 gchar *path;
1329
1330 path = qdev_get_canonical_path(child);
1331 visit_type_str(v, &path, name, errp);
1332 g_free(path);
1333}
1334
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001335static void qdev_release_child_property(DeviceState *dev, const char *name,
1336 void *opaque)
1337{
1338 DeviceState *child = opaque;
1339
1340 qdev_unref(child);
1341}
1342
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001343void qdev_property_add_child(DeviceState *dev, const char *name,
1344 DeviceState *child, Error **errp)
1345{
1346 gchar *type;
1347
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001348 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001349
1350 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001351 NULL, qdev_release_child_property,
1352 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001353
1354 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001355 g_assert(child->parent == NULL);
1356 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001357
1358 g_free(type);
1359}
1360
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001361static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1362 const char *name, Error **errp)
1363{
1364 DeviceState **child = opaque;
1365 gchar *path;
1366
1367 if (*child) {
1368 path = qdev_get_canonical_path(*child);
1369 visit_type_str(v, &path, name, errp);
1370 g_free(path);
1371 } else {
1372 path = (gchar *)"";
1373 visit_type_str(v, &path, name, errp);
1374 }
1375}
1376
1377static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1378 const char *name, Error **errp)
1379{
1380 DeviceState **child = opaque;
1381 bool ambiguous = false;
1382 const char *type;
1383 char *path;
1384
1385 type = qdev_property_get_type(dev, name, NULL);
1386
1387 visit_type_str(v, &path, name, errp);
1388
1389 if (*child) {
1390 qdev_unref(*child);
1391 }
1392
1393 if (strcmp(path, "") != 0) {
1394 DeviceState *target;
1395
1396 target = qdev_resolve_path(path, &ambiguous);
1397 if (target) {
1398 gchar *target_type;
1399
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001400 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001401 if (strcmp(target_type, type) == 0) {
1402 *child = target;
1403 qdev_ref(target);
1404 } else {
1405 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1406 }
1407
1408 g_free(target_type);
1409 } else {
1410 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1411 }
1412 } else {
1413 *child = NULL;
1414 }
1415
1416 g_free(path);
1417}
1418
1419void qdev_property_add_link(DeviceState *dev, const char *name,
1420 const char *type, DeviceState **child,
1421 Error **errp)
1422{
1423 gchar *full_type;
1424
1425 full_type = g_strdup_printf("link<%s>", type);
1426
1427 qdev_property_add(dev, name, full_type,
1428 qdev_get_link_property,
1429 qdev_set_link_property,
1430 NULL, child, errp);
1431
1432 g_free(full_type);
1433}
1434
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001435gchar *qdev_get_canonical_path(DeviceState *dev)
1436{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001437 DeviceState *root = qdev_get_root();
1438 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001439
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001440 while (dev != root) {
1441 DeviceProperty *prop = NULL;
1442
1443 g_assert(dev->parent != NULL);
1444
1445 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1446 if (!strstart(prop->type, "child<", NULL)) {
1447 continue;
1448 }
1449
1450 if (prop->opaque == dev) {
1451 if (path) {
1452 newpath = g_strdup_printf("%s/%s", prop->name, path);
1453 g_free(path);
1454 path = newpath;
1455 } else {
1456 path = g_strdup(prop->name);
1457 }
1458 break;
1459 }
1460 }
1461
1462 g_assert(prop != NULL);
1463
1464 dev = dev->parent;
1465 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001466
1467 newpath = g_strdup_printf("/%s", path);
1468 g_free(path);
1469
1470 return newpath;
1471}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001472
1473static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1474 gchar **parts,
1475 int index)
1476{
1477 DeviceProperty *prop;
1478 DeviceState *child;
1479
1480 if (parts[index] == NULL) {
1481 return parent;
1482 }
1483
1484 if (strcmp(parts[index], "") == 0) {
1485 return qdev_resolve_abs_path(parent, parts, index + 1);
1486 }
1487
1488 prop = qdev_property_find(parent, parts[index]);
1489 if (prop == NULL) {
1490 return NULL;
1491 }
1492
1493 child = NULL;
1494 if (strstart(prop->type, "link<", NULL)) {
1495 DeviceState **pchild = prop->opaque;
1496 if (*pchild) {
1497 child = *pchild;
1498 }
1499 } else if (strstart(prop->type, "child<", NULL)) {
1500 child = prop->opaque;
1501 }
1502
1503 if (!child) {
1504 return NULL;
1505 }
1506
1507 return qdev_resolve_abs_path(child, parts, index + 1);
1508}
1509
1510static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1511 gchar **parts,
1512 bool *ambiguous)
1513{
1514 DeviceState *dev;
1515 DeviceProperty *prop;
1516
1517 dev = qdev_resolve_abs_path(parent, parts, 0);
1518
1519 QTAILQ_FOREACH(prop, &parent->properties, node) {
1520 DeviceState *found;
1521
1522 if (!strstart(prop->type, "child<", NULL)) {
1523 continue;
1524 }
1525
1526 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1527 if (found) {
1528 if (dev) {
1529 if (ambiguous) {
1530 *ambiguous = true;
1531 }
1532 return NULL;
1533 }
1534 dev = found;
1535 }
1536
1537 if (ambiguous && *ambiguous) {
1538 return NULL;
1539 }
1540 }
1541
1542 return dev;
1543}
1544
1545DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1546{
1547 bool partial_path = true;
1548 DeviceState *dev;
1549 gchar **parts;
1550
1551 parts = g_strsplit(path, "/", 0);
1552 if (parts == NULL || parts[0] == NULL) {
1553 g_strfreev(parts);
1554 return qdev_get_root();
1555 }
1556
1557 if (strcmp(parts[0], "") == 0) {
1558 partial_path = false;
1559 }
1560
1561 if (partial_path) {
1562 if (ambiguous) {
1563 *ambiguous = false;
1564 }
1565 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1566 } else {
1567 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1568 }
1569
1570 g_strfreev(parts);
1571
1572 return dev;
1573}
1574
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001575typedef struct StringProperty
1576{
1577 char *(*get)(DeviceState *, Error **);
1578 void (*set)(DeviceState *, const char *, Error **);
1579} StringProperty;
1580
1581static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1582 const char *name, Error **errp)
1583{
1584 StringProperty *prop = opaque;
1585 char *value;
1586
1587 value = prop->get(dev, errp);
1588 if (value) {
1589 visit_type_str(v, &value, name, errp);
1590 g_free(value);
1591 }
1592}
1593
1594static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1595 const char *name, Error **errp)
1596{
1597 StringProperty *prop = opaque;
1598 char *value;
1599 Error *local_err = NULL;
1600
1601 visit_type_str(v, &value, name, &local_err);
1602 if (local_err) {
1603 error_propagate(errp, local_err);
1604 return;
1605 }
1606
1607 prop->set(dev, value, errp);
1608 g_free(value);
1609}
1610
1611static void qdev_property_release_str(DeviceState *dev, const char *name,
1612 void *opaque)
1613{
1614 StringProperty *prop = opaque;
1615 g_free(prop);
1616}
1617
1618void qdev_property_add_str(DeviceState *dev, const char *name,
1619 char *(*get)(DeviceState *, Error **),
1620 void (*set)(DeviceState *, const char *, Error **),
1621 Error **errp)
1622{
1623 StringProperty *prop = g_malloc0(sizeof(*prop));
1624
1625 prop->get = get;
1626 prop->set = set;
1627
1628 qdev_property_add(dev, name, "string",
1629 get ? qdev_property_get_str : NULL,
1630 set ? qdev_property_set_str : NULL,
1631 qdev_property_release_str,
1632 prop, errp);
1633}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001634
1635void qdev_machine_init(void)
1636{
1637 qdev_get_peripheral_anon();
1638 qdev_get_peripheral();
1639}
Anthony Liguori32fea402011-12-16 14:34:46 -06001640
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001641static void device_initfn(Object *obj)
1642{
1643 DeviceState *dev = DEVICE(obj);
1644 Property *prop;
1645
1646 if (qdev_hotplug) {
1647 dev->hotplugged = 1;
1648 qdev_hot_added = true;
1649 }
1650
1651 dev->instance_id_alias = -1;
1652 QTAILQ_INIT(&dev->properties);
1653 dev->state = DEV_STATE_CREATED;
1654
1655 qdev_prop_set_defaults(dev, qdev_get_props(dev));
1656 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
1657 qdev_property_add_legacy(dev, prop, NULL);
1658 qdev_property_add_static(dev, prop, NULL);
1659 }
1660
1661 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
1662}
1663
Anthony Liguori94afdad2011-12-04 11:36:01 -06001664void device_reset(DeviceState *dev)
1665{
1666 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1667
1668 if (klass->reset) {
1669 klass->reset(dev);
1670 }
1671}
1672
Anthony Liguori32fea402011-12-16 14:34:46 -06001673static TypeInfo device_type_info = {
1674 .name = TYPE_DEVICE,
1675 .parent = TYPE_OBJECT,
1676 .instance_size = sizeof(DeviceState),
Anthony Liguori9674bfe2011-12-22 15:06:37 -06001677 .instance_init = device_initfn,
Anthony Liguori32fea402011-12-16 14:34:46 -06001678 .abstract = true,
1679 .class_size = sizeof(DeviceClass),
1680};
1681
1682static void init_qdev(void)
1683{
1684 type_register_static(&device_type_info);
1685}
1686
1687device_init(init_qdev);