blob: a8c24deba6c63eb0c501af1b08dc064c4c6549e4 [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 Hoffmann0958b4c2009-10-26 15:56:45 +010041DeviceInfo *device_info_list;
Paul Brookaae94602009-05-14 22:35:06 +010042
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020043static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 const BusInfo *info);
45static BusState *qbus_find(const char *path);
46
Paul Brookaae94602009-05-14 22:35:06 +010047/* Register a new device type. */
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060048static void qdev_subclass_init(ObjectClass *klass, void *data)
49{
50 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori94afdad2011-12-04 11:36:01 -060051
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060052 dc->info = data;
Anthony Liguori94afdad2011-12-04 11:36:01 -060053 dc->reset = dc->info->reset;
54
55 /* Poison to try to detect future uses */
56 dc->info->reset = NULL;
Anthony Liguori3dde52d2011-12-04 14:37:06 -060057
58 if (dc->info->class_init) {
59 dc->info->class_init(klass, data);
60 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060061}
62
63DeviceInfo *qdev_get_info(DeviceState *dev)
64{
65 return DEVICE_GET_CLASS(dev)->info;
66}
67
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060068void qdev_register_subclass(DeviceInfo *info, const char *parent)
Paul Brookaae94602009-05-14 22:35:06 +010069{
Anthony Liguori32fea402011-12-16 14:34:46 -060070 TypeInfo type_info = {};
71
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020072 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020073 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010074
Anthony Liguori32fea402011-12-16 14:34:46 -060075 type_info.name = info->name;
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060076 type_info.parent = parent;
Anthony Liguori32fea402011-12-16 14:34:46 -060077 type_info.instance_size = info->size;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060078 type_info.class_init = qdev_subclass_init;
79 type_info.class_data = info;
Anthony Liguori32fea402011-12-16 14:34:46 -060080
81 type_register_static(&type_info);
82
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020083 info->next = device_info_list;
84 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010085}
86
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060087void qdev_register(DeviceInfo *info)
88{
89 qdev_register_subclass(info, TYPE_DEVICE);
90}
91
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020092static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
93{
94 DeviceInfo *info;
95
Gerd Hoffmann3320e562009-07-15 13:43:33 +020096 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020097 for (info = device_info_list; info != NULL; info = info->next) {
98 if (bus_info && info->bus_info != bus_info)
99 continue;
100 if (strcmp(info->name, name) != 0)
101 continue;
102 return info;
103 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200104
105 /* failing that check the aliases */
106 for (info = device_info_list; info != NULL; info = info->next) {
107 if (bus_info && info->bus_info != bus_info)
108 continue;
109 if (!info->alias)
110 continue;
111 if (strcmp(info->alias, name) != 0)
112 continue;
113 return info;
114 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200115 return NULL;
116}
117
Blue Swirla369da52011-09-27 19:15:42 +0000118bool qdev_exists(const char *name)
119{
120 return !!qdev_find_info(NULL, name);
121}
Anthony Liguori40021f02011-12-04 12:22:06 -0600122
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100123static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
124 Error **errp);
125
Markus Armbruster0c175422010-02-19 19:12:18 +0100126static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +0100127{
Paul Brookaae94602009-05-14 22:35:06 +0100128 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600129 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100130
Markus Armbruster0c175422010-02-19 19:12:18 +0100131 assert(bus->info == info->bus_info);
Anthony Liguori32fea402011-12-16 14:34:46 -0600132 dev = DEVICE(object_new(info->name));
Paul Brook02e2da42009-05-23 00:05:19 +0100133 dev->parent_bus = bus;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600134 qdev_prop_set_defaults(dev, qdev_get_info(dev)->props);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200135 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100136 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200137 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200138 if (qdev_hotplug) {
139 assert(bus->allow_hotplug);
140 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700141 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200142 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200143 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600144 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200145 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600146
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600147 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600148 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100149 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600150 }
151
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600152 for (prop = qdev_get_info(dev)->bus_info->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600153 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100154 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600155 }
156
Anthony Liguoricd34d662011-12-12 14:29:43 -0600157 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
158
Paul Brookaae94602009-05-14 22:35:06 +0100159 return dev;
160}
161
Markus Armbruster0c175422010-02-19 19:12:18 +0100162/* Create a new device. This only initializes the device state structure
163 and allows properties to be set. qdev_init should be called to
164 initialize the actual device emulation. */
165DeviceState *qdev_create(BusState *bus, const char *name)
166{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000167 DeviceState *dev;
168
169 dev = qdev_try_create(bus, name);
170 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100171 if (bus) {
172 hw_error("Unknown device '%s' for bus '%s'\n", name,
173 bus->info->name);
174 } else {
175 hw_error("Unknown device '%s' for default sysbus\n", name);
176 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000177 }
178
179 return dev;
180}
181
182DeviceState *qdev_try_create(BusState *bus, const char *name)
183{
Markus Armbruster0c175422010-02-19 19:12:18 +0100184 DeviceInfo *info;
185
186 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100187 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100188 }
189
190 info = qdev_find_info(bus->info, name);
191 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000192 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100193 }
194
195 return qdev_create_from_info(bus, info);
196}
197
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100198static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200199{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100200 error_printf("name \"%s\", bus %s",
201 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200202 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100203 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200204 }
205 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100206 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200207 }
208 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100209 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200210 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100211 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200212}
213
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200214static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200215{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200216 DeviceState *dev = opaque;
217
218 if (strcmp(name, "driver") == 0)
219 return 0;
220 if (strcmp(name, "bus") == 0)
221 return 0;
222
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100223 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200224 return -1;
225 }
226 return 0;
227}
228
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100229int qdev_device_help(QemuOpts *opts)
230{
231 const char *driver;
232 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100233 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100234
235 driver = qemu_opt_get(opts, "driver");
236 if (driver && !strcmp(driver, "?")) {
237 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100238 if (info->no_user) {
239 continue; /* not available, don't show */
240 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100241 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100242 }
243 return 1;
244 }
245
Markus Armbruster542379f2011-11-08 11:00:38 +0100246 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100247 return 0;
248 }
249
250 info = qdev_find_info(NULL, driver);
251 if (!info) {
252 return 0;
253 }
254
255 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100256 /*
257 * TODO Properties without a parser are just for dirty hacks.
258 * qdev_prop_ptr is the only such PropertyInfo. It's marked
259 * for removal. This conditional should be removed along with
260 * it.
261 */
262 if (!prop->info->parse) {
263 continue; /* no way to set it, don't show */
264 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100265 error_printf("%s.%s=%s\n", info->name, prop->name,
266 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100267 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200268 for (prop = info->bus_info->props; prop && prop->name; prop++) {
269 if (!prop->info->parse) {
270 continue; /* no way to set it, don't show */
271 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100272 error_printf("%s.%s=%s\n", info->name, prop->name,
273 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200274 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100275 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100276}
277
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600278static DeviceState *qdev_get_peripheral(void)
279{
280 static DeviceState *dev;
281
282 if (dev == NULL) {
283 dev = qdev_create(NULL, "container");
284 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
285 qdev_init_nofail(dev);
286 }
287
288 return dev;
289}
290
Anthony Liguori8eb02832011-12-12 14:29:37 -0600291static DeviceState *qdev_get_peripheral_anon(void)
292{
293 static DeviceState *dev;
294
295 if (dev == NULL) {
296 dev = qdev_create(NULL, "container");
297 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
298 qdev_init_nofail(dev);
299 }
300
301 return dev;
302}
303
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200304DeviceState *qdev_device_add(QemuOpts *opts)
305{
306 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200307 DeviceInfo *info;
308 DeviceState *qdev;
309 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200310
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200311 driver = qemu_opt_get(opts, "driver");
312 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100313 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200314 return NULL;
315 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200316
317 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200318 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100319 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100320 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100321 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200322 return NULL;
323 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200324
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200325 /* find bus */
326 path = qemu_opt_get(opts, "bus");
327 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200328 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100329 if (!bus) {
330 return NULL;
331 }
332 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100333 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
334 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100335 return NULL;
336 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200337 } else {
338 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100339 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100340 qerror_report(QERR_NO_BUS_FOR_DEVICE,
341 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100342 return NULL;
343 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200344 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200345 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100346 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200347 return NULL;
348 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200349
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200350 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100351 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200352 id = qemu_opts_id(opts);
353 if (id) {
354 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600355 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600356 } else {
357 static int anon_count;
358 gchar *name = g_strdup_printf("device[%d]", anon_count++);
359 qdev_property_add_child(qdev_get_peripheral_anon(), name,
360 qdev, NULL);
361 g_free(name);
362 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200363 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
364 qdev_free(qdev);
365 return NULL;
366 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200367 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100368 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200369 return NULL;
370 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200371 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200372 return qdev;
373}
374
Paul Brookaae94602009-05-14 22:35:06 +0100375/* Initialize a device. Device properties should be set before calling
376 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200377 calling this function.
378 On failure, destroy the device and return negative value.
379 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200380int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100381{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200382 int rc;
383
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200384 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600385 rc = qdev_get_info(dev)->init(dev, qdev_get_info(dev));
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200386 if (rc < 0) {
387 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200388 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200389 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600390 if (qdev_get_info(dev)->vmsd) {
391 vmstate_register_with_alias_id(dev, -1, qdev_get_info(dev)->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200392 dev->instance_id_alias,
393 dev->alias_required_for_version);
394 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200395 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600396 if (dev->hotplugged) {
397 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200398 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200399 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100400}
401
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200402void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
403 int required_for_version)
404{
405 assert(dev->state == DEV_STATE_CREATED);
406 dev->instance_id_alias = alias_id;
407 dev->alias_required_for_version = required_for_version;
408}
409
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200410int qdev_unplug(DeviceState *dev)
411{
412 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100413 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200414 return -1;
415 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600416 assert(qdev_get_info(dev)->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530417
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700418 qdev_hot_removed = true;
419
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600420 return qdev_get_info(dev)->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200421}
422
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900423static int qdev_reset_one(DeviceState *dev, void *opaque)
424{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600425 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900426
427 return 0;
428}
429
430BusState *sysbus_get_default(void)
431{
Stefan Weil68694892010-12-16 19:33:22 +0100432 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900433 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100434 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900435 return main_system_bus;
436}
437
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900438static int qbus_reset_one(BusState *bus, void *opaque)
439{
440 if (bus->info->reset) {
441 return bus->info->reset(bus);
442 }
443 return 0;
444}
445
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900446void qdev_reset_all(DeviceState *dev)
447{
448 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
449}
450
Isaku Yamahata80376c32010-12-20 14:33:35 +0900451void qbus_reset_all_fn(void *opaque)
452{
453 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200454 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900455}
456
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200457/* can be used as ->unplug() callback for the simple cases */
458int qdev_simple_unplug_cb(DeviceState *dev)
459{
460 /* just zap it */
461 qdev_free(dev);
462 return 0;
463}
464
Michael Tokarev3b29a102011-04-06 17:51:59 +0400465
466/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200467 returning an error value. This is okay during machine creation.
468 Don't use for hotplug, because there callers need to recover from
469 failure. Exception: if you know the device's init() callback can't
470 fail, then qdev_init_nofail() can't fail either, and is therefore
471 usable even then. But relying on the device implementation that
472 way is somewhat unclean, and best avoided. */
473void qdev_init_nofail(DeviceState *dev)
474{
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600475 DeviceInfo *info = qdev_get_info(dev);
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200476
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200477 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200478 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200479 exit(1);
480 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200481}
482
Anthony Liguori44677de2011-12-12 14:29:26 -0600483static void qdev_property_del_all(DeviceState *dev)
484{
485 while (!QTAILQ_EMPTY(&dev->properties)) {
486 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
487
488 QTAILQ_REMOVE(&dev->properties, prop, node);
489
490 if (prop->release) {
491 prop->release(dev, prop->name, prop->opaque);
492 }
493
494 g_free(prop->name);
495 g_free(prop->type);
496 g_free(prop);
497 }
498}
499
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600500static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
501{
502 DeviceProperty *prop;
503
504 QTAILQ_FOREACH(prop, &dev->properties, node) {
505 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
506 break;
507 }
508 }
509
510 g_assert(prop != NULL);
511
512 QTAILQ_REMOVE(&dev->properties, prop, node);
513
514 if (prop->release) {
515 prop->release(dev, prop->name, prop->opaque);
516 }
517
518 g_free(prop->name);
519 g_free(prop->type);
520 g_free(prop);
521}
522
Paul Brook02e2da42009-05-23 00:05:19 +0100523/* Unlink device from bus and free the structure. */
524void qdev_free(DeviceState *dev)
525{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200526 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200527 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200528
Anthony Liguori44677de2011-12-12 14:29:26 -0600529 qdev_property_del_all(dev);
530
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200531 if (dev->state == DEV_STATE_INITIALIZED) {
532 while (dev->num_child_bus) {
533 bus = QLIST_FIRST(&dev->child_bus);
534 qbus_free(bus);
535 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600536 if (qdev_get_info(dev)->vmsd)
537 vmstate_unregister(dev, qdev_get_info(dev)->vmsd, dev);
538 if (qdev_get_info(dev)->exit)
539 qdev_get_info(dev)->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200540 if (dev->opts)
541 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200542 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200543 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600544 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200545 if (prop->info->free) {
546 prop->info->free(dev, prop);
547 }
548 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600549 if (dev->parent) {
550 qdev_property_del_child(dev->parent, dev, NULL);
551 }
552 if (dev->ref != 0) {
553 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
554 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600555 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100556}
557
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200558void qdev_machine_creation_done(void)
559{
560 /*
561 * ok, initial machine setup is done, starting from now we can
562 * only create hotpluggable devices
563 */
564 qdev_hotplug = 1;
565}
566
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700567bool qdev_machine_modified(void)
568{
569 return qdev_hot_added || qdev_hot_removed;
570}
571
Paul Brookaae94602009-05-14 22:35:06 +0100572/* Get a character (serial) device interface. */
573CharDriverState *qdev_init_chardev(DeviceState *dev)
574{
575 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530576
577 /* FIXME: This function needs to go away: use chardev properties! */
578 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100579}
580
Paul Brook02e2da42009-05-23 00:05:19 +0100581BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100582{
Paul Brook02e2da42009-05-23 00:05:19 +0100583 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100584}
585
Paul Brookaae94602009-05-14 22:35:06 +0100586void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
587{
588 assert(dev->num_gpio_in == 0);
589 dev->num_gpio_in = n;
590 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
591}
592
593void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
594{
595 assert(dev->num_gpio_out == 0);
596 dev->num_gpio_out = n;
597 dev->gpio_out = pins;
598}
599
600qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
601{
602 assert(n >= 0 && n < dev->num_gpio_in);
603 return dev->gpio_in[n];
604}
605
606void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
607{
608 assert(n >= 0 && n < dev->num_gpio_out);
609 dev->gpio_out[n] = pin;
610}
611
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200612void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
613{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200614 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200615 if (nd->vlan)
616 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
617 if (nd->netdev)
618 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530619 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200620 qdev_prop_exists(dev, "vectors")) {
621 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
622 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100623 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200624}
625
Paul Brook02e2da42009-05-23 00:05:19 +0100626BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100627{
Paul Brook02e2da42009-05-23 00:05:19 +0100628 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100629
Blue Swirl72cf2d42009-09-12 07:36:22 +0000630 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100631 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100632 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100633 }
634 }
635 return NULL;
636}
637
Anthony Liguori81699d82010-11-19 18:55:58 +0900638int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
639 qbus_walkerfn *busfn, void *opaque)
640{
641 DeviceState *dev;
642 int err;
643
644 if (busfn) {
645 err = busfn(bus, opaque);
646 if (err) {
647 return err;
648 }
649 }
650
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200651 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900652 err = qdev_walk_children(dev, devfn, busfn, opaque);
653 if (err < 0) {
654 return err;
655 }
656 }
657
658 return 0;
659}
660
661int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
662 qbus_walkerfn *busfn, void *opaque)
663{
664 BusState *bus;
665 int err;
666
667 if (devfn) {
668 err = devfn(dev, opaque);
669 if (err) {
670 return err;
671 }
672 }
673
674 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
675 err = qbus_walk_children(bus, devfn, busfn, opaque);
676 if (err < 0) {
677 return err;
678 }
679 }
680
681 return 0;
682}
683
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200684static BusState *qbus_find_recursive(BusState *bus, const char *name,
685 const BusInfo *info)
686{
687 DeviceState *dev;
688 BusState *child, *ret;
689 int match = 1;
690
691 if (name && (strcmp(bus->name, name) != 0)) {
692 match = 0;
693 }
694 if (info && (bus->info != info)) {
695 match = 0;
696 }
697 if (match) {
698 return bus;
699 }
700
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200701 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000702 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200703 ret = qbus_find_recursive(child, name, info);
704 if (ret) {
705 return ret;
706 }
707 }
708 }
709 return NULL;
710}
711
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900712DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200713{
714 DeviceState *dev, *ret;
715 BusState *child;
716
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200717 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200718 if (dev->id && strcmp(dev->id, id) == 0)
719 return dev;
720 QLIST_FOREACH(child, &dev->child_bus, sibling) {
721 ret = qdev_find_recursive(child, id);
722 if (ret) {
723 return ret;
724 }
725 }
726 }
727 return NULL;
728}
729
Markus Armbruster53db16b2010-02-18 18:55:59 +0100730static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200731{
732 BusState *child;
733 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200734
Markus Armbruster53db16b2010-02-18 18:55:59 +0100735 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600736 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000737 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100738 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200739 sep = ", ";
740 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100741 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200742}
743
Markus Armbruster53db16b2010-02-18 18:55:59 +0100744static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200745{
746 DeviceState *dev;
747 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200748
Markus Armbruster53db16b2010-02-18 18:55:59 +0100749 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200750 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600751 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200752 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100753 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200754 sep = ", ";
755 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100756 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200757}
758
759static BusState *qbus_find_bus(DeviceState *dev, char *elem)
760{
761 BusState *child;
762
Blue Swirl72cf2d42009-09-12 07:36:22 +0000763 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200764 if (strcmp(child->name, elem) == 0) {
765 return child;
766 }
767 }
768 return NULL;
769}
770
771static DeviceState *qbus_find_dev(BusState *bus, char *elem)
772{
773 DeviceState *dev;
774
775 /*
776 * try to match in order:
777 * (1) instance id, if present
778 * (2) driver name
779 * (3) driver alias, if present
780 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200781 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200782 if (dev->id && strcmp(dev->id, elem) == 0) {
783 return dev;
784 }
785 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200786 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600787 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200788 return dev;
789 }
790 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200791 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600792 if (qdev_get_info(dev)->alias && strcmp(qdev_get_info(dev)->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200793 return dev;
794 }
795 }
796 return NULL;
797}
798
799static BusState *qbus_find(const char *path)
800{
801 DeviceState *dev;
802 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100803 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200804 int pos, len;
805
806 /* find start element */
807 if (path[0] == '/') {
808 bus = main_system_bus;
809 pos = 0;
810 } else {
811 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100812 assert(!path[0]);
813 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200814 }
815 bus = qbus_find_recursive(main_system_bus, elem, NULL);
816 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100817 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200818 return NULL;
819 }
820 pos = len;
821 }
822
823 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100824 assert(path[pos] == '/' || !path[pos]);
825 while (path[pos] == '/') {
826 pos++;
827 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200828 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200829 return bus;
830 }
831
832 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100833 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
834 assert(0);
835 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200836 }
837 pos += len;
838 dev = qbus_find_dev(bus, elem);
839 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100840 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100841 if (!monitor_cur_is_qmp()) {
842 qbus_list_dev(bus);
843 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200844 return NULL;
845 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100846
847 assert(path[pos] == '/' || !path[pos]);
848 while (path[pos] == '/') {
849 pos++;
850 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200851 if (path[pos] == '\0') {
852 /* last specified element is a device. If it has exactly
853 * one child bus accept it nevertheless */
854 switch (dev->num_child_bus) {
855 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100856 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200857 return NULL;
858 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000859 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200860 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100861 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100862 if (!monitor_cur_is_qmp()) {
863 qbus_list_bus(dev);
864 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200865 return NULL;
866 }
867 }
868
869 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100870 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
871 assert(0);
872 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200873 }
874 pos += len;
875 bus = qbus_find_bus(dev, elem);
876 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100877 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100878 if (!monitor_cur_is_qmp()) {
879 qbus_list_bus(dev);
880 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200881 return NULL;
882 }
883 }
884}
885
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200886void qbus_create_inplace(BusState *bus, BusInfo *info,
887 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100888{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200889 char *buf;
890 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100891
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200892 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100893 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200894
895 if (name) {
896 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500897 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200898 } else if (parent && parent->id) {
899 /* parent device has id -> use it for bus name */
900 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500901 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200902 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
903 bus->name = buf;
904 } else {
905 /* no id -> use lowercase bus type for bus name */
906 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500907 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200908 len = snprintf(buf, len, "%s.%d", info->name,
909 parent ? parent->num_child_bus : 0);
910 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200911 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200912 bus->name = buf;
913 }
914
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200915 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100916 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000917 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200918 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900919 } else if (bus != main_system_bus) {
920 /* TODO: once all bus devices are qdevified,
921 only reset handler for main_system_bus should be registered here. */
922 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100923 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200924}
925
926BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
927{
928 BusState *bus;
929
Anthony Liguori7267c092011-08-20 22:09:37 -0500930 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200931 bus->qdev_allocated = 1;
932 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100933 return bus;
934}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100935
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900936static void main_system_bus_create(void)
937{
938 /* assign main_system_bus before qbus_create_inplace()
939 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500940 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900941 main_system_bus->qdev_allocated = 1;
942 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
943 "main-system-bus");
944}
945
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200946void qbus_free(BusState *bus)
947{
948 DeviceState *dev;
949
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200950 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200951 qdev_free(dev);
952 }
953 if (bus->parent) {
954 QLIST_REMOVE(bus, sibling);
955 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900956 } else {
957 assert(bus != main_system_bus); /* main_system_bus is never freed */
958 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200959 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500960 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200961 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500962 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200963 }
964}
965
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100966#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
967static void qbus_print(Monitor *mon, BusState *bus, int indent);
968
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200969static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
970 const char *prefix, int indent)
971{
972 char buf[64];
973
974 if (!props)
975 return;
976 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100977 /*
978 * TODO Properties without a print method are just for dirty
979 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
980 * marked for removal. The test props->info->print should be
981 * removed along with it.
982 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200983 if (props->info->print) {
984 props->info->print(dev, props, buf, sizeof(buf));
985 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
986 }
987 props++;
988 }
989}
990
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100991static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
992{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100993 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600994 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200995 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100996 indent += 2;
997 if (dev->num_gpio_in) {
998 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
999 }
1000 if (dev->num_gpio_out) {
1001 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1002 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -06001003 qdev_print_props(mon, dev, qdev_get_info(dev)->props, "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001004 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001005 if (dev->parent_bus->info->print_dev)
1006 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001007 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001008 qbus_print(mon, child, indent);
1009 }
1010}
1011
1012static void qbus_print(Monitor *mon, BusState *bus, int indent)
1013{
1014 struct DeviceState *dev;
1015
1016 qdev_printf("bus: %s\n", bus->name);
1017 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001018 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001019 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001020 qdev_print(mon, dev, indent);
1021 }
1022}
1023#undef qdev_printf
1024
1025void do_info_qtree(Monitor *mon)
1026{
1027 if (main_system_bus)
1028 qbus_print(mon, main_system_bus, 0);
1029}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001030
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001031void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001032{
1033 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001034
1035 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +01001036 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001037 }
1038}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001039
Markus Armbruster8bc27242010-02-10 20:52:01 +01001040int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001041{
1042 QemuOpts *opts;
1043
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001044 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001045 if (!opts) {
1046 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001047 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001048 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1049 qemu_opts_del(opts);
1050 return 0;
1051 }
1052 if (!qdev_device_add(opts)) {
1053 qemu_opts_del(opts);
1054 return -1;
1055 }
1056 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001057}
1058
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001059int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001060{
1061 const char *id = qdict_get_str(qdict, "id");
1062 DeviceState *dev;
1063
1064 dev = qdev_find_recursive(main_system_bus, id);
1065 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001066 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1067 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001068 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001069 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001070}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001071
1072static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1073{
1074 int l = 0;
1075
1076 if (dev && dev->parent_bus) {
1077 char *d;
1078 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1079 if (dev->parent_bus->info->get_fw_dev_path) {
1080 d = dev->parent_bus->info->get_fw_dev_path(dev);
1081 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001082 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001083 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001084 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001085 }
1086 }
1087 l += snprintf(p + l , size - l, "/");
1088
1089 return l;
1090}
1091
1092char* qdev_get_fw_dev_path(DeviceState *dev)
1093{
1094 char path[128];
1095 int l;
1096
1097 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1098
1099 path[l-1] = '\0';
1100
1101 return strdup(path);
1102}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001103
Anthony Liguoricd34d662011-12-12 14:29:43 -06001104char *qdev_get_type(DeviceState *dev, Error **errp)
1105{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001106 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001107}
1108
Anthony Liguori85ed3032011-12-12 14:29:25 -06001109void qdev_ref(DeviceState *dev)
1110{
1111 dev->ref++;
1112}
1113
1114void qdev_unref(DeviceState *dev)
1115{
1116 g_assert(dev->ref > 0);
1117 dev->ref--;
1118}
Anthony Liguori44677de2011-12-12 14:29:26 -06001119
1120void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1121 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1122 DevicePropertyRelease *release,
1123 void *opaque, Error **errp)
1124{
1125 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1126
1127 prop->name = g_strdup(name);
1128 prop->type = g_strdup(type);
1129
1130 prop->get = get;
1131 prop->set = set;
1132 prop->release = release;
1133 prop->opaque = opaque;
1134
1135 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1136}
1137
1138static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1139{
1140 DeviceProperty *prop;
1141
1142 QTAILQ_FOREACH(prop, &dev->properties, node) {
1143 if (strcmp(prop->name, name) == 0) {
1144 return prop;
1145 }
1146 }
1147
1148 return NULL;
1149}
1150
1151void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1152 Error **errp)
1153{
1154 DeviceProperty *prop = qdev_property_find(dev, name);
1155
1156 if (prop == NULL) {
1157 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1158 return;
1159 }
1160
1161 if (!prop->get) {
1162 error_set(errp, QERR_PERMISSION_DENIED);
1163 } else {
1164 prop->get(dev, v, prop->opaque, name, errp);
1165 }
1166}
1167
1168void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1169 Error **errp)
1170{
1171 DeviceProperty *prop = qdev_property_find(dev, name);
1172
1173 if (prop == NULL) {
1174 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1175 return;
1176 }
1177
1178 if (!prop->set) {
1179 error_set(errp, QERR_PERMISSION_DENIED);
1180 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001181 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001182 }
1183}
1184
1185const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1186{
1187 DeviceProperty *prop = qdev_property_find(dev, name);
1188
1189 if (prop == NULL) {
1190 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1191 return NULL;
1192 }
1193
1194 return prop->type;
1195}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001196
1197/**
1198 * Legacy property handling
1199 */
1200
1201static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1202 const char *name, Error **errp)
1203{
1204 Property *prop = opaque;
1205
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001206 char buffer[1024];
1207 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001208
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001209 prop->info->print(dev, prop, buffer, sizeof(buffer));
1210 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001211}
1212
1213static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1214 const char *name, Error **errp)
1215{
1216 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001217 Error *local_err = NULL;
1218 char *ptr = NULL;
1219 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001220
1221 if (dev->state != DEV_STATE_CREATED) {
1222 error_set(errp, QERR_PERMISSION_DENIED);
1223 return;
1224 }
1225
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001226 visit_type_str(v, &ptr, name, &local_err);
1227 if (local_err) {
1228 error_propagate(errp, local_err);
1229 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001230 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001231
1232 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001233 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001234 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001235}
1236
1237/**
1238 * @qdev_add_legacy_property - adds a legacy property
1239 *
1240 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001241 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001242 *
1243 * Legacy properties are always processed as strings. The format of the string
1244 * depends on the property type.
1245 */
1246void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1247 Error **errp)
1248{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001249 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001250
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001251 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001252 type = g_strdup_printf("legacy<%s>",
1253 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001254
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001255 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001256 prop->info->print ? qdev_get_legacy_property : NULL,
1257 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001258 NULL,
1259 prop, errp);
1260
1261 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001262 g_free(name);
1263}
1264
1265/**
1266 * @qdev_property_add_static - add a @Property to a device.
1267 *
1268 * Static properties access data in a struct. The actual type of the
1269 * property and the field depends on the property type.
1270 */
1271void qdev_property_add_static(DeviceState *dev, Property *prop,
1272 Error **errp)
1273{
1274 qdev_property_add(dev, prop->name, prop->info->name,
1275 prop->info->get, prop->info->set,
1276 NULL,
1277 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001278}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001279
1280DeviceState *qdev_get_root(void)
1281{
1282 static DeviceState *qdev_root;
1283
1284 if (!qdev_root) {
1285 qdev_root = qdev_create(NULL, "container");
1286 qdev_init_nofail(qdev_root);
1287 }
1288
1289 return qdev_root;
1290}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001291
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001292static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1293 const char *name, Error **errp)
1294{
1295 DeviceState *child = opaque;
1296 gchar *path;
1297
1298 path = qdev_get_canonical_path(child);
1299 visit_type_str(v, &path, name, errp);
1300 g_free(path);
1301}
1302
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001303static void qdev_release_child_property(DeviceState *dev, const char *name,
1304 void *opaque)
1305{
1306 DeviceState *child = opaque;
1307
1308 qdev_unref(child);
1309}
1310
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001311void qdev_property_add_child(DeviceState *dev, const char *name,
1312 DeviceState *child, Error **errp)
1313{
1314 gchar *type;
1315
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001316 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001317
1318 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001319 NULL, qdev_release_child_property,
1320 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001321
1322 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001323 g_assert(child->parent == NULL);
1324 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001325
1326 g_free(type);
1327}
1328
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001329static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1330 const char *name, Error **errp)
1331{
1332 DeviceState **child = opaque;
1333 gchar *path;
1334
1335 if (*child) {
1336 path = qdev_get_canonical_path(*child);
1337 visit_type_str(v, &path, name, errp);
1338 g_free(path);
1339 } else {
1340 path = (gchar *)"";
1341 visit_type_str(v, &path, name, errp);
1342 }
1343}
1344
1345static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1346 const char *name, Error **errp)
1347{
1348 DeviceState **child = opaque;
1349 bool ambiguous = false;
1350 const char *type;
1351 char *path;
1352
1353 type = qdev_property_get_type(dev, name, NULL);
1354
1355 visit_type_str(v, &path, name, errp);
1356
1357 if (*child) {
1358 qdev_unref(*child);
1359 }
1360
1361 if (strcmp(path, "") != 0) {
1362 DeviceState *target;
1363
1364 target = qdev_resolve_path(path, &ambiguous);
1365 if (target) {
1366 gchar *target_type;
1367
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001368 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001369 if (strcmp(target_type, type) == 0) {
1370 *child = target;
1371 qdev_ref(target);
1372 } else {
1373 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1374 }
1375
1376 g_free(target_type);
1377 } else {
1378 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1379 }
1380 } else {
1381 *child = NULL;
1382 }
1383
1384 g_free(path);
1385}
1386
1387void qdev_property_add_link(DeviceState *dev, const char *name,
1388 const char *type, DeviceState **child,
1389 Error **errp)
1390{
1391 gchar *full_type;
1392
1393 full_type = g_strdup_printf("link<%s>", type);
1394
1395 qdev_property_add(dev, name, full_type,
1396 qdev_get_link_property,
1397 qdev_set_link_property,
1398 NULL, child, errp);
1399
1400 g_free(full_type);
1401}
1402
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001403gchar *qdev_get_canonical_path(DeviceState *dev)
1404{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001405 DeviceState *root = qdev_get_root();
1406 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001407
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001408 while (dev != root) {
1409 DeviceProperty *prop = NULL;
1410
1411 g_assert(dev->parent != NULL);
1412
1413 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1414 if (!strstart(prop->type, "child<", NULL)) {
1415 continue;
1416 }
1417
1418 if (prop->opaque == dev) {
1419 if (path) {
1420 newpath = g_strdup_printf("%s/%s", prop->name, path);
1421 g_free(path);
1422 path = newpath;
1423 } else {
1424 path = g_strdup(prop->name);
1425 }
1426 break;
1427 }
1428 }
1429
1430 g_assert(prop != NULL);
1431
1432 dev = dev->parent;
1433 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001434
1435 newpath = g_strdup_printf("/%s", path);
1436 g_free(path);
1437
1438 return newpath;
1439}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001440
1441static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1442 gchar **parts,
1443 int index)
1444{
1445 DeviceProperty *prop;
1446 DeviceState *child;
1447
1448 if (parts[index] == NULL) {
1449 return parent;
1450 }
1451
1452 if (strcmp(parts[index], "") == 0) {
1453 return qdev_resolve_abs_path(parent, parts, index + 1);
1454 }
1455
1456 prop = qdev_property_find(parent, parts[index]);
1457 if (prop == NULL) {
1458 return NULL;
1459 }
1460
1461 child = NULL;
1462 if (strstart(prop->type, "link<", NULL)) {
1463 DeviceState **pchild = prop->opaque;
1464 if (*pchild) {
1465 child = *pchild;
1466 }
1467 } else if (strstart(prop->type, "child<", NULL)) {
1468 child = prop->opaque;
1469 }
1470
1471 if (!child) {
1472 return NULL;
1473 }
1474
1475 return qdev_resolve_abs_path(child, parts, index + 1);
1476}
1477
1478static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1479 gchar **parts,
1480 bool *ambiguous)
1481{
1482 DeviceState *dev;
1483 DeviceProperty *prop;
1484
1485 dev = qdev_resolve_abs_path(parent, parts, 0);
1486
1487 QTAILQ_FOREACH(prop, &parent->properties, node) {
1488 DeviceState *found;
1489
1490 if (!strstart(prop->type, "child<", NULL)) {
1491 continue;
1492 }
1493
1494 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1495 if (found) {
1496 if (dev) {
1497 if (ambiguous) {
1498 *ambiguous = true;
1499 }
1500 return NULL;
1501 }
1502 dev = found;
1503 }
1504
1505 if (ambiguous && *ambiguous) {
1506 return NULL;
1507 }
1508 }
1509
1510 return dev;
1511}
1512
1513DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1514{
1515 bool partial_path = true;
1516 DeviceState *dev;
1517 gchar **parts;
1518
1519 parts = g_strsplit(path, "/", 0);
1520 if (parts == NULL || parts[0] == NULL) {
1521 g_strfreev(parts);
1522 return qdev_get_root();
1523 }
1524
1525 if (strcmp(parts[0], "") == 0) {
1526 partial_path = false;
1527 }
1528
1529 if (partial_path) {
1530 if (ambiguous) {
1531 *ambiguous = false;
1532 }
1533 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1534 } else {
1535 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1536 }
1537
1538 g_strfreev(parts);
1539
1540 return dev;
1541}
1542
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001543typedef struct StringProperty
1544{
1545 char *(*get)(DeviceState *, Error **);
1546 void (*set)(DeviceState *, const char *, Error **);
1547} StringProperty;
1548
1549static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1550 const char *name, Error **errp)
1551{
1552 StringProperty *prop = opaque;
1553 char *value;
1554
1555 value = prop->get(dev, errp);
1556 if (value) {
1557 visit_type_str(v, &value, name, errp);
1558 g_free(value);
1559 }
1560}
1561
1562static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1563 const char *name, Error **errp)
1564{
1565 StringProperty *prop = opaque;
1566 char *value;
1567 Error *local_err = NULL;
1568
1569 visit_type_str(v, &value, name, &local_err);
1570 if (local_err) {
1571 error_propagate(errp, local_err);
1572 return;
1573 }
1574
1575 prop->set(dev, value, errp);
1576 g_free(value);
1577}
1578
1579static void qdev_property_release_str(DeviceState *dev, const char *name,
1580 void *opaque)
1581{
1582 StringProperty *prop = opaque;
1583 g_free(prop);
1584}
1585
1586void qdev_property_add_str(DeviceState *dev, const char *name,
1587 char *(*get)(DeviceState *, Error **),
1588 void (*set)(DeviceState *, const char *, Error **),
1589 Error **errp)
1590{
1591 StringProperty *prop = g_malloc0(sizeof(*prop));
1592
1593 prop->get = get;
1594 prop->set = set;
1595
1596 qdev_property_add(dev, name, "string",
1597 get ? qdev_property_get_str : NULL,
1598 set ? qdev_property_set_str : NULL,
1599 qdev_property_release_str,
1600 prop, errp);
1601}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001602
1603void qdev_machine_init(void)
1604{
1605 qdev_get_peripheral_anon();
1606 qdev_get_peripheral();
1607}
Anthony Liguori32fea402011-12-16 14:34:46 -06001608
Anthony Liguori94afdad2011-12-04 11:36:01 -06001609void device_reset(DeviceState *dev)
1610{
1611 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1612
1613 if (klass->reset) {
1614 klass->reset(dev);
1615 }
1616}
1617
Anthony Liguori32fea402011-12-16 14:34:46 -06001618static TypeInfo device_type_info = {
1619 .name = TYPE_DEVICE,
1620 .parent = TYPE_OBJECT,
1621 .instance_size = sizeof(DeviceState),
1622 .abstract = true,
1623 .class_size = sizeof(DeviceClass),
1624};
1625
1626static void init_qdev(void)
1627{
1628 type_register_static(&device_type_info);
1629}
1630
1631device_init(init_qdev);