blob: c4b5284fdc07d03689fb814af5dcb5fc5bd08dd8 [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 Liguori30fbb9f2011-12-04 11:08:36 -060057}
58
59DeviceInfo *qdev_get_info(DeviceState *dev)
60{
61 return DEVICE_GET_CLASS(dev)->info;
62}
63
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060064void qdev_register_subclass(DeviceInfo *info, const char *parent)
Paul Brookaae94602009-05-14 22:35:06 +010065{
Anthony Liguori32fea402011-12-16 14:34:46 -060066 TypeInfo type_info = {};
67
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020068 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020069 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010070
Anthony Liguori32fea402011-12-16 14:34:46 -060071 type_info.name = info->name;
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060072 type_info.parent = parent;
Anthony Liguori32fea402011-12-16 14:34:46 -060073 type_info.instance_size = info->size;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060074 type_info.class_init = qdev_subclass_init;
75 type_info.class_data = info;
Anthony Liguori32fea402011-12-16 14:34:46 -060076
77 type_register_static(&type_info);
78
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020079 info->next = device_info_list;
80 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010081}
82
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060083void qdev_register(DeviceInfo *info)
84{
85 qdev_register_subclass(info, TYPE_DEVICE);
86}
87
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020088static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
89{
90 DeviceInfo *info;
91
Gerd Hoffmann3320e562009-07-15 13:43:33 +020092 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020093 for (info = device_info_list; info != NULL; info = info->next) {
94 if (bus_info && info->bus_info != bus_info)
95 continue;
96 if (strcmp(info->name, name) != 0)
97 continue;
98 return info;
99 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200100
101 /* failing that check the aliases */
102 for (info = device_info_list; info != NULL; info = info->next) {
103 if (bus_info && info->bus_info != bus_info)
104 continue;
105 if (!info->alias)
106 continue;
107 if (strcmp(info->alias, name) != 0)
108 continue;
109 return info;
110 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200111 return NULL;
112}
113
Blue Swirla369da52011-09-27 19:15:42 +0000114bool qdev_exists(const char *name)
115{
116 return !!qdev_find_info(NULL, name);
117}
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100118static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
119 Error **errp);
120
Markus Armbruster0c175422010-02-19 19:12:18 +0100121static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +0100122{
Paul Brookaae94602009-05-14 22:35:06 +0100123 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600124 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100125
Markus Armbruster0c175422010-02-19 19:12:18 +0100126 assert(bus->info == info->bus_info);
Anthony Liguori32fea402011-12-16 14:34:46 -0600127 dev = DEVICE(object_new(info->name));
Paul Brook02e2da42009-05-23 00:05:19 +0100128 dev->parent_bus = bus;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600129 qdev_prop_set_defaults(dev, qdev_get_info(dev)->props);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200130 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100131 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200132 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200133 if (qdev_hotplug) {
134 assert(bus->allow_hotplug);
135 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700136 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200137 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200138 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600139 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200140 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600141
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600142 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600143 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100144 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600145 }
146
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600147 for (prop = qdev_get_info(dev)->bus_info->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 Liguoricd34d662011-12-12 14:29:43 -0600152 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
153
Paul Brookaae94602009-05-14 22:35:06 +0100154 return dev;
155}
156
Markus Armbruster0c175422010-02-19 19:12:18 +0100157/* Create a new device. This only initializes the device state structure
158 and allows properties to be set. qdev_init should be called to
159 initialize the actual device emulation. */
160DeviceState *qdev_create(BusState *bus, const char *name)
161{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000162 DeviceState *dev;
163
164 dev = qdev_try_create(bus, name);
165 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100166 if (bus) {
167 hw_error("Unknown device '%s' for bus '%s'\n", name,
168 bus->info->name);
169 } else {
170 hw_error("Unknown device '%s' for default sysbus\n", name);
171 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000172 }
173
174 return dev;
175}
176
177DeviceState *qdev_try_create(BusState *bus, const char *name)
178{
Markus Armbruster0c175422010-02-19 19:12:18 +0100179 DeviceInfo *info;
180
181 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100182 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100183 }
184
185 info = qdev_find_info(bus->info, name);
186 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000187 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100188 }
189
190 return qdev_create_from_info(bus, info);
191}
192
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100193static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200194{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100195 error_printf("name \"%s\", bus %s",
196 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200197 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100198 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200199 }
200 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100201 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200202 }
203 if (info->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
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100224int qdev_device_help(QemuOpts *opts)
225{
226 const char *driver;
227 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100228 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100229
230 driver = qemu_opt_get(opts, "driver");
231 if (driver && !strcmp(driver, "?")) {
232 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100233 if (info->no_user) {
234 continue; /* not available, don't show */
235 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100236 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100237 }
238 return 1;
239 }
240
Markus Armbruster542379f2011-11-08 11:00:38 +0100241 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100242 return 0;
243 }
244
245 info = qdev_find_info(NULL, driver);
246 if (!info) {
247 return 0;
248 }
249
250 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100251 /*
252 * TODO Properties without a parser are just for dirty hacks.
253 * qdev_prop_ptr is the only such PropertyInfo. It's marked
254 * for removal. This conditional should be removed along with
255 * it.
256 */
257 if (!prop->info->parse) {
258 continue; /* no way to set it, don't show */
259 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100260 error_printf("%s.%s=%s\n", info->name, prop->name,
261 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100262 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200263 for (prop = info->bus_info->props; prop && prop->name; prop++) {
264 if (!prop->info->parse) {
265 continue; /* no way to set it, don't show */
266 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100267 error_printf("%s.%s=%s\n", info->name, prop->name,
268 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200269 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100270 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100271}
272
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600273static DeviceState *qdev_get_peripheral(void)
274{
275 static DeviceState *dev;
276
277 if (dev == NULL) {
278 dev = qdev_create(NULL, "container");
279 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
280 qdev_init_nofail(dev);
281 }
282
283 return dev;
284}
285
Anthony Liguori8eb02832011-12-12 14:29:37 -0600286static DeviceState *qdev_get_peripheral_anon(void)
287{
288 static DeviceState *dev;
289
290 if (dev == NULL) {
291 dev = qdev_create(NULL, "container");
292 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
293 qdev_init_nofail(dev);
294 }
295
296 return dev;
297}
298
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200299DeviceState *qdev_device_add(QemuOpts *opts)
300{
301 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200302 DeviceInfo *info;
303 DeviceState *qdev;
304 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200305
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200306 driver = qemu_opt_get(opts, "driver");
307 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100308 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200309 return NULL;
310 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200311
312 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200313 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100314 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100315 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100316 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200317 return NULL;
318 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200319
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200320 /* find bus */
321 path = qemu_opt_get(opts, "bus");
322 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200323 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100324 if (!bus) {
325 return NULL;
326 }
327 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100328 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
329 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100330 return NULL;
331 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200332 } else {
333 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100334 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100335 qerror_report(QERR_NO_BUS_FOR_DEVICE,
336 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100337 return NULL;
338 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200339 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200340 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100341 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200342 return NULL;
343 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200344
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200345 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100346 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200347 id = qemu_opts_id(opts);
348 if (id) {
349 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600350 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600351 } else {
352 static int anon_count;
353 gchar *name = g_strdup_printf("device[%d]", anon_count++);
354 qdev_property_add_child(qdev_get_peripheral_anon(), name,
355 qdev, NULL);
356 g_free(name);
357 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200358 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
359 qdev_free(qdev);
360 return NULL;
361 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200362 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100363 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200364 return NULL;
365 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200366 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200367 return qdev;
368}
369
Paul Brookaae94602009-05-14 22:35:06 +0100370/* Initialize a device. Device properties should be set before calling
371 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200372 calling this function.
373 On failure, destroy the device and return negative value.
374 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200375int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100376{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200377 int rc;
378
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200379 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600380 rc = qdev_get_info(dev)->init(dev, qdev_get_info(dev));
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200381 if (rc < 0) {
382 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200383 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200384 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600385 if (qdev_get_info(dev)->vmsd) {
386 vmstate_register_with_alias_id(dev, -1, qdev_get_info(dev)->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200387 dev->instance_id_alias,
388 dev->alias_required_for_version);
389 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200390 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600391 if (dev->hotplugged) {
392 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200393 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200394 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100395}
396
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200397void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
398 int required_for_version)
399{
400 assert(dev->state == DEV_STATE_CREATED);
401 dev->instance_id_alias = alias_id;
402 dev->alias_required_for_version = required_for_version;
403}
404
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200405int qdev_unplug(DeviceState *dev)
406{
407 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100408 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200409 return -1;
410 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600411 assert(qdev_get_info(dev)->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530412
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700413 qdev_hot_removed = true;
414
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600415 return qdev_get_info(dev)->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200416}
417
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900418static int qdev_reset_one(DeviceState *dev, void *opaque)
419{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600420 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900421
422 return 0;
423}
424
425BusState *sysbus_get_default(void)
426{
Stefan Weil68694892010-12-16 19:33:22 +0100427 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900428 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100429 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900430 return main_system_bus;
431}
432
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900433static int qbus_reset_one(BusState *bus, void *opaque)
434{
435 if (bus->info->reset) {
436 return bus->info->reset(bus);
437 }
438 return 0;
439}
440
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900441void qdev_reset_all(DeviceState *dev)
442{
443 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
444}
445
Isaku Yamahata80376c32010-12-20 14:33:35 +0900446void qbus_reset_all_fn(void *opaque)
447{
448 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200449 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900450}
451
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200452/* can be used as ->unplug() callback for the simple cases */
453int qdev_simple_unplug_cb(DeviceState *dev)
454{
455 /* just zap it */
456 qdev_free(dev);
457 return 0;
458}
459
Michael Tokarev3b29a102011-04-06 17:51:59 +0400460
461/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200462 returning an error value. This is okay during machine creation.
463 Don't use for hotplug, because there callers need to recover from
464 failure. Exception: if you know the device's init() callback can't
465 fail, then qdev_init_nofail() can't fail either, and is therefore
466 usable even then. But relying on the device implementation that
467 way is somewhat unclean, and best avoided. */
468void qdev_init_nofail(DeviceState *dev)
469{
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600470 DeviceInfo *info = qdev_get_info(dev);
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200471
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200472 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200473 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200474 exit(1);
475 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200476}
477
Anthony Liguori44677de2011-12-12 14:29:26 -0600478static void qdev_property_del_all(DeviceState *dev)
479{
480 while (!QTAILQ_EMPTY(&dev->properties)) {
481 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
482
483 QTAILQ_REMOVE(&dev->properties, prop, node);
484
485 if (prop->release) {
486 prop->release(dev, prop->name, prop->opaque);
487 }
488
489 g_free(prop->name);
490 g_free(prop->type);
491 g_free(prop);
492 }
493}
494
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600495static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
496{
497 DeviceProperty *prop;
498
499 QTAILQ_FOREACH(prop, &dev->properties, node) {
500 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
501 break;
502 }
503 }
504
505 g_assert(prop != NULL);
506
507 QTAILQ_REMOVE(&dev->properties, prop, node);
508
509 if (prop->release) {
510 prop->release(dev, prop->name, prop->opaque);
511 }
512
513 g_free(prop->name);
514 g_free(prop->type);
515 g_free(prop);
516}
517
Paul Brook02e2da42009-05-23 00:05:19 +0100518/* Unlink device from bus and free the structure. */
519void qdev_free(DeviceState *dev)
520{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200521 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200522 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200523
Anthony Liguori44677de2011-12-12 14:29:26 -0600524 qdev_property_del_all(dev);
525
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200526 if (dev->state == DEV_STATE_INITIALIZED) {
527 while (dev->num_child_bus) {
528 bus = QLIST_FIRST(&dev->child_bus);
529 qbus_free(bus);
530 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600531 if (qdev_get_info(dev)->vmsd)
532 vmstate_unregister(dev, qdev_get_info(dev)->vmsd, dev);
533 if (qdev_get_info(dev)->exit)
534 qdev_get_info(dev)->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200535 if (dev->opts)
536 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200537 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200538 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600539 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200540 if (prop->info->free) {
541 prop->info->free(dev, prop);
542 }
543 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600544 if (dev->parent) {
545 qdev_property_del_child(dev->parent, dev, NULL);
546 }
547 if (dev->ref != 0) {
548 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
549 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600550 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100551}
552
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200553void qdev_machine_creation_done(void)
554{
555 /*
556 * ok, initial machine setup is done, starting from now we can
557 * only create hotpluggable devices
558 */
559 qdev_hotplug = 1;
560}
561
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700562bool qdev_machine_modified(void)
563{
564 return qdev_hot_added || qdev_hot_removed;
565}
566
Paul Brookaae94602009-05-14 22:35:06 +0100567/* Get a character (serial) device interface. */
568CharDriverState *qdev_init_chardev(DeviceState *dev)
569{
570 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530571
572 /* FIXME: This function needs to go away: use chardev properties! */
573 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100574}
575
Paul Brook02e2da42009-05-23 00:05:19 +0100576BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100577{
Paul Brook02e2da42009-05-23 00:05:19 +0100578 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100579}
580
Paul Brookaae94602009-05-14 22:35:06 +0100581void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
582{
583 assert(dev->num_gpio_in == 0);
584 dev->num_gpio_in = n;
585 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
586}
587
588void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
589{
590 assert(dev->num_gpio_out == 0);
591 dev->num_gpio_out = n;
592 dev->gpio_out = pins;
593}
594
595qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
596{
597 assert(n >= 0 && n < dev->num_gpio_in);
598 return dev->gpio_in[n];
599}
600
601void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
602{
603 assert(n >= 0 && n < dev->num_gpio_out);
604 dev->gpio_out[n] = pin;
605}
606
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200607void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
608{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200609 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200610 if (nd->vlan)
611 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
612 if (nd->netdev)
613 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530614 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200615 qdev_prop_exists(dev, "vectors")) {
616 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
617 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100618 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200619}
620
Paul Brook02e2da42009-05-23 00:05:19 +0100621BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100622{
Paul Brook02e2da42009-05-23 00:05:19 +0100623 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100624
Blue Swirl72cf2d42009-09-12 07:36:22 +0000625 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100626 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100627 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100628 }
629 }
630 return NULL;
631}
632
Anthony Liguori81699d82010-11-19 18:55:58 +0900633int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
634 qbus_walkerfn *busfn, void *opaque)
635{
636 DeviceState *dev;
637 int err;
638
639 if (busfn) {
640 err = busfn(bus, opaque);
641 if (err) {
642 return err;
643 }
644 }
645
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200646 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900647 err = qdev_walk_children(dev, devfn, busfn, opaque);
648 if (err < 0) {
649 return err;
650 }
651 }
652
653 return 0;
654}
655
656int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
657 qbus_walkerfn *busfn, void *opaque)
658{
659 BusState *bus;
660 int err;
661
662 if (devfn) {
663 err = devfn(dev, opaque);
664 if (err) {
665 return err;
666 }
667 }
668
669 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
670 err = qbus_walk_children(bus, devfn, busfn, opaque);
671 if (err < 0) {
672 return err;
673 }
674 }
675
676 return 0;
677}
678
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200679static BusState *qbus_find_recursive(BusState *bus, const char *name,
680 const BusInfo *info)
681{
682 DeviceState *dev;
683 BusState *child, *ret;
684 int match = 1;
685
686 if (name && (strcmp(bus->name, name) != 0)) {
687 match = 0;
688 }
689 if (info && (bus->info != info)) {
690 match = 0;
691 }
692 if (match) {
693 return bus;
694 }
695
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200696 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000697 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200698 ret = qbus_find_recursive(child, name, info);
699 if (ret) {
700 return ret;
701 }
702 }
703 }
704 return NULL;
705}
706
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900707DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200708{
709 DeviceState *dev, *ret;
710 BusState *child;
711
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200712 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200713 if (dev->id && strcmp(dev->id, id) == 0)
714 return dev;
715 QLIST_FOREACH(child, &dev->child_bus, sibling) {
716 ret = qdev_find_recursive(child, id);
717 if (ret) {
718 return ret;
719 }
720 }
721 }
722 return NULL;
723}
724
Markus Armbruster53db16b2010-02-18 18:55:59 +0100725static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200726{
727 BusState *child;
728 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200729
Markus Armbruster53db16b2010-02-18 18:55:59 +0100730 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600731 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000732 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100733 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200734 sep = ", ";
735 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100736 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200737}
738
Markus Armbruster53db16b2010-02-18 18:55:59 +0100739static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200740{
741 DeviceState *dev;
742 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200743
Markus Armbruster53db16b2010-02-18 18:55:59 +0100744 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200745 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600746 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200747 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100748 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200749 sep = ", ";
750 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100751 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200752}
753
754static BusState *qbus_find_bus(DeviceState *dev, char *elem)
755{
756 BusState *child;
757
Blue Swirl72cf2d42009-09-12 07:36:22 +0000758 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200759 if (strcmp(child->name, elem) == 0) {
760 return child;
761 }
762 }
763 return NULL;
764}
765
766static DeviceState *qbus_find_dev(BusState *bus, char *elem)
767{
768 DeviceState *dev;
769
770 /*
771 * try to match in order:
772 * (1) instance id, if present
773 * (2) driver name
774 * (3) driver alias, if present
775 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200776 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200777 if (dev->id && strcmp(dev->id, elem) == 0) {
778 return dev;
779 }
780 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200781 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600782 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200783 return dev;
784 }
785 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200786 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600787 if (qdev_get_info(dev)->alias && strcmp(qdev_get_info(dev)->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200788 return dev;
789 }
790 }
791 return NULL;
792}
793
794static BusState *qbus_find(const char *path)
795{
796 DeviceState *dev;
797 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100798 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200799 int pos, len;
800
801 /* find start element */
802 if (path[0] == '/') {
803 bus = main_system_bus;
804 pos = 0;
805 } else {
806 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100807 assert(!path[0]);
808 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200809 }
810 bus = qbus_find_recursive(main_system_bus, elem, NULL);
811 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100812 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200813 return NULL;
814 }
815 pos = len;
816 }
817
818 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100819 assert(path[pos] == '/' || !path[pos]);
820 while (path[pos] == '/') {
821 pos++;
822 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200823 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200824 return bus;
825 }
826
827 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100828 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
829 assert(0);
830 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200831 }
832 pos += len;
833 dev = qbus_find_dev(bus, elem);
834 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100835 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100836 if (!monitor_cur_is_qmp()) {
837 qbus_list_dev(bus);
838 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200839 return NULL;
840 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100841
842 assert(path[pos] == '/' || !path[pos]);
843 while (path[pos] == '/') {
844 pos++;
845 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200846 if (path[pos] == '\0') {
847 /* last specified element is a device. If it has exactly
848 * one child bus accept it nevertheless */
849 switch (dev->num_child_bus) {
850 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100851 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200852 return NULL;
853 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000854 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200855 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100856 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100857 if (!monitor_cur_is_qmp()) {
858 qbus_list_bus(dev);
859 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200860 return NULL;
861 }
862 }
863
864 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100865 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
866 assert(0);
867 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200868 }
869 pos += len;
870 bus = qbus_find_bus(dev, elem);
871 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100872 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100873 if (!monitor_cur_is_qmp()) {
874 qbus_list_bus(dev);
875 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200876 return NULL;
877 }
878 }
879}
880
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200881void qbus_create_inplace(BusState *bus, BusInfo *info,
882 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100883{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200884 char *buf;
885 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100886
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200887 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100888 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200889
890 if (name) {
891 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500892 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200893 } else if (parent && parent->id) {
894 /* parent device has id -> use it for bus name */
895 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500896 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200897 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
898 bus->name = buf;
899 } else {
900 /* no id -> use lowercase bus type for bus name */
901 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500902 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200903 len = snprintf(buf, len, "%s.%d", info->name,
904 parent ? parent->num_child_bus : 0);
905 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200906 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200907 bus->name = buf;
908 }
909
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200910 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100911 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000912 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200913 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900914 } else if (bus != main_system_bus) {
915 /* TODO: once all bus devices are qdevified,
916 only reset handler for main_system_bus should be registered here. */
917 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100918 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200919}
920
921BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
922{
923 BusState *bus;
924
Anthony Liguori7267c092011-08-20 22:09:37 -0500925 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200926 bus->qdev_allocated = 1;
927 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100928 return bus;
929}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100930
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900931static void main_system_bus_create(void)
932{
933 /* assign main_system_bus before qbus_create_inplace()
934 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500935 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900936 main_system_bus->qdev_allocated = 1;
937 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
938 "main-system-bus");
939}
940
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200941void qbus_free(BusState *bus)
942{
943 DeviceState *dev;
944
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200945 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200946 qdev_free(dev);
947 }
948 if (bus->parent) {
949 QLIST_REMOVE(bus, sibling);
950 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900951 } else {
952 assert(bus != main_system_bus); /* main_system_bus is never freed */
953 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200954 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500955 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200956 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500957 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200958 }
959}
960
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100961#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
962static void qbus_print(Monitor *mon, BusState *bus, int indent);
963
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200964static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
965 const char *prefix, int indent)
966{
967 char buf[64];
968
969 if (!props)
970 return;
971 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100972 /*
973 * TODO Properties without a print method are just for dirty
974 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
975 * marked for removal. The test props->info->print should be
976 * removed along with it.
977 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200978 if (props->info->print) {
979 props->info->print(dev, props, buf, sizeof(buf));
980 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
981 }
982 props++;
983 }
984}
985
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100986static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
987{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100988 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600989 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200990 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100991 indent += 2;
992 if (dev->num_gpio_in) {
993 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
994 }
995 if (dev->num_gpio_out) {
996 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
997 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600998 qdev_print_props(mon, dev, qdev_get_info(dev)->props, "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200999 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001000 if (dev->parent_bus->info->print_dev)
1001 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001002 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001003 qbus_print(mon, child, indent);
1004 }
1005}
1006
1007static void qbus_print(Monitor *mon, BusState *bus, int indent)
1008{
1009 struct DeviceState *dev;
1010
1011 qdev_printf("bus: %s\n", bus->name);
1012 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001013 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001014 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001015 qdev_print(mon, dev, indent);
1016 }
1017}
1018#undef qdev_printf
1019
1020void do_info_qtree(Monitor *mon)
1021{
1022 if (main_system_bus)
1023 qbus_print(mon, main_system_bus, 0);
1024}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001025
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001026void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001027{
1028 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001029
1030 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +01001031 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001032 }
1033}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001034
Markus Armbruster8bc27242010-02-10 20:52:01 +01001035int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001036{
1037 QemuOpts *opts;
1038
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001039 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001040 if (!opts) {
1041 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001042 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001043 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1044 qemu_opts_del(opts);
1045 return 0;
1046 }
1047 if (!qdev_device_add(opts)) {
1048 qemu_opts_del(opts);
1049 return -1;
1050 }
1051 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001052}
1053
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001054int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001055{
1056 const char *id = qdict_get_str(qdict, "id");
1057 DeviceState *dev;
1058
1059 dev = qdev_find_recursive(main_system_bus, id);
1060 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001061 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1062 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001063 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001064 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001065}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001066
1067static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1068{
1069 int l = 0;
1070
1071 if (dev && dev->parent_bus) {
1072 char *d;
1073 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1074 if (dev->parent_bus->info->get_fw_dev_path) {
1075 d = dev->parent_bus->info->get_fw_dev_path(dev);
1076 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001077 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001078 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001079 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001080 }
1081 }
1082 l += snprintf(p + l , size - l, "/");
1083
1084 return l;
1085}
1086
1087char* qdev_get_fw_dev_path(DeviceState *dev)
1088{
1089 char path[128];
1090 int l;
1091
1092 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1093
1094 path[l-1] = '\0';
1095
1096 return strdup(path);
1097}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001098
Anthony Liguoricd34d662011-12-12 14:29:43 -06001099char *qdev_get_type(DeviceState *dev, Error **errp)
1100{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001101 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001102}
1103
Anthony Liguori85ed3032011-12-12 14:29:25 -06001104void qdev_ref(DeviceState *dev)
1105{
1106 dev->ref++;
1107}
1108
1109void qdev_unref(DeviceState *dev)
1110{
1111 g_assert(dev->ref > 0);
1112 dev->ref--;
1113}
Anthony Liguori44677de2011-12-12 14:29:26 -06001114
1115void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1116 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1117 DevicePropertyRelease *release,
1118 void *opaque, Error **errp)
1119{
1120 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1121
1122 prop->name = g_strdup(name);
1123 prop->type = g_strdup(type);
1124
1125 prop->get = get;
1126 prop->set = set;
1127 prop->release = release;
1128 prop->opaque = opaque;
1129
1130 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1131}
1132
1133static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1134{
1135 DeviceProperty *prop;
1136
1137 QTAILQ_FOREACH(prop, &dev->properties, node) {
1138 if (strcmp(prop->name, name) == 0) {
1139 return prop;
1140 }
1141 }
1142
1143 return NULL;
1144}
1145
1146void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1147 Error **errp)
1148{
1149 DeviceProperty *prop = qdev_property_find(dev, name);
1150
1151 if (prop == NULL) {
1152 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1153 return;
1154 }
1155
1156 if (!prop->get) {
1157 error_set(errp, QERR_PERMISSION_DENIED);
1158 } else {
1159 prop->get(dev, v, prop->opaque, name, errp);
1160 }
1161}
1162
1163void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1164 Error **errp)
1165{
1166 DeviceProperty *prop = qdev_property_find(dev, name);
1167
1168 if (prop == NULL) {
1169 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1170 return;
1171 }
1172
1173 if (!prop->set) {
1174 error_set(errp, QERR_PERMISSION_DENIED);
1175 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001176 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001177 }
1178}
1179
1180const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1181{
1182 DeviceProperty *prop = qdev_property_find(dev, name);
1183
1184 if (prop == NULL) {
1185 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1186 return NULL;
1187 }
1188
1189 return prop->type;
1190}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001191
1192/**
1193 * Legacy property handling
1194 */
1195
1196static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1197 const char *name, Error **errp)
1198{
1199 Property *prop = opaque;
1200
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001201 char buffer[1024];
1202 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001203
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001204 prop->info->print(dev, prop, buffer, sizeof(buffer));
1205 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001206}
1207
1208static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1209 const char *name, Error **errp)
1210{
1211 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001212 Error *local_err = NULL;
1213 char *ptr = NULL;
1214 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001215
1216 if (dev->state != DEV_STATE_CREATED) {
1217 error_set(errp, QERR_PERMISSION_DENIED);
1218 return;
1219 }
1220
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001221 visit_type_str(v, &ptr, name, &local_err);
1222 if (local_err) {
1223 error_propagate(errp, local_err);
1224 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001225 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001226
1227 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001228 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001229 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001230}
1231
1232/**
1233 * @qdev_add_legacy_property - adds a legacy property
1234 *
1235 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001236 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001237 *
1238 * Legacy properties are always processed as strings. The format of the string
1239 * depends on the property type.
1240 */
1241void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1242 Error **errp)
1243{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001244 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001245
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001246 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001247 type = g_strdup_printf("legacy<%s>",
1248 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001249
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001250 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001251 prop->info->print ? qdev_get_legacy_property : NULL,
1252 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001253 NULL,
1254 prop, errp);
1255
1256 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001257 g_free(name);
1258}
1259
1260/**
1261 * @qdev_property_add_static - add a @Property to a device.
1262 *
1263 * Static properties access data in a struct. The actual type of the
1264 * property and the field depends on the property type.
1265 */
1266void qdev_property_add_static(DeviceState *dev, Property *prop,
1267 Error **errp)
1268{
1269 qdev_property_add(dev, prop->name, prop->info->name,
1270 prop->info->get, prop->info->set,
1271 NULL,
1272 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001273}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001274
1275DeviceState *qdev_get_root(void)
1276{
1277 static DeviceState *qdev_root;
1278
1279 if (!qdev_root) {
1280 qdev_root = qdev_create(NULL, "container");
1281 qdev_init_nofail(qdev_root);
1282 }
1283
1284 return qdev_root;
1285}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001286
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001287static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1288 const char *name, Error **errp)
1289{
1290 DeviceState *child = opaque;
1291 gchar *path;
1292
1293 path = qdev_get_canonical_path(child);
1294 visit_type_str(v, &path, name, errp);
1295 g_free(path);
1296}
1297
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001298static void qdev_release_child_property(DeviceState *dev, const char *name,
1299 void *opaque)
1300{
1301 DeviceState *child = opaque;
1302
1303 qdev_unref(child);
1304}
1305
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001306void qdev_property_add_child(DeviceState *dev, const char *name,
1307 DeviceState *child, Error **errp)
1308{
1309 gchar *type;
1310
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001311 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001312
1313 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001314 NULL, qdev_release_child_property,
1315 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001316
1317 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001318 g_assert(child->parent == NULL);
1319 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001320
1321 g_free(type);
1322}
1323
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001324static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1325 const char *name, Error **errp)
1326{
1327 DeviceState **child = opaque;
1328 gchar *path;
1329
1330 if (*child) {
1331 path = qdev_get_canonical_path(*child);
1332 visit_type_str(v, &path, name, errp);
1333 g_free(path);
1334 } else {
1335 path = (gchar *)"";
1336 visit_type_str(v, &path, name, errp);
1337 }
1338}
1339
1340static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1341 const char *name, Error **errp)
1342{
1343 DeviceState **child = opaque;
1344 bool ambiguous = false;
1345 const char *type;
1346 char *path;
1347
1348 type = qdev_property_get_type(dev, name, NULL);
1349
1350 visit_type_str(v, &path, name, errp);
1351
1352 if (*child) {
1353 qdev_unref(*child);
1354 }
1355
1356 if (strcmp(path, "") != 0) {
1357 DeviceState *target;
1358
1359 target = qdev_resolve_path(path, &ambiguous);
1360 if (target) {
1361 gchar *target_type;
1362
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001363 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001364 if (strcmp(target_type, type) == 0) {
1365 *child = target;
1366 qdev_ref(target);
1367 } else {
1368 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1369 }
1370
1371 g_free(target_type);
1372 } else {
1373 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1374 }
1375 } else {
1376 *child = NULL;
1377 }
1378
1379 g_free(path);
1380}
1381
1382void qdev_property_add_link(DeviceState *dev, const char *name,
1383 const char *type, DeviceState **child,
1384 Error **errp)
1385{
1386 gchar *full_type;
1387
1388 full_type = g_strdup_printf("link<%s>", type);
1389
1390 qdev_property_add(dev, name, full_type,
1391 qdev_get_link_property,
1392 qdev_set_link_property,
1393 NULL, child, errp);
1394
1395 g_free(full_type);
1396}
1397
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001398gchar *qdev_get_canonical_path(DeviceState *dev)
1399{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001400 DeviceState *root = qdev_get_root();
1401 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001402
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001403 while (dev != root) {
1404 DeviceProperty *prop = NULL;
1405
1406 g_assert(dev->parent != NULL);
1407
1408 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1409 if (!strstart(prop->type, "child<", NULL)) {
1410 continue;
1411 }
1412
1413 if (prop->opaque == dev) {
1414 if (path) {
1415 newpath = g_strdup_printf("%s/%s", prop->name, path);
1416 g_free(path);
1417 path = newpath;
1418 } else {
1419 path = g_strdup(prop->name);
1420 }
1421 break;
1422 }
1423 }
1424
1425 g_assert(prop != NULL);
1426
1427 dev = dev->parent;
1428 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001429
1430 newpath = g_strdup_printf("/%s", path);
1431 g_free(path);
1432
1433 return newpath;
1434}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001435
1436static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1437 gchar **parts,
1438 int index)
1439{
1440 DeviceProperty *prop;
1441 DeviceState *child;
1442
1443 if (parts[index] == NULL) {
1444 return parent;
1445 }
1446
1447 if (strcmp(parts[index], "") == 0) {
1448 return qdev_resolve_abs_path(parent, parts, index + 1);
1449 }
1450
1451 prop = qdev_property_find(parent, parts[index]);
1452 if (prop == NULL) {
1453 return NULL;
1454 }
1455
1456 child = NULL;
1457 if (strstart(prop->type, "link<", NULL)) {
1458 DeviceState **pchild = prop->opaque;
1459 if (*pchild) {
1460 child = *pchild;
1461 }
1462 } else if (strstart(prop->type, "child<", NULL)) {
1463 child = prop->opaque;
1464 }
1465
1466 if (!child) {
1467 return NULL;
1468 }
1469
1470 return qdev_resolve_abs_path(child, parts, index + 1);
1471}
1472
1473static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1474 gchar **parts,
1475 bool *ambiguous)
1476{
1477 DeviceState *dev;
1478 DeviceProperty *prop;
1479
1480 dev = qdev_resolve_abs_path(parent, parts, 0);
1481
1482 QTAILQ_FOREACH(prop, &parent->properties, node) {
1483 DeviceState *found;
1484
1485 if (!strstart(prop->type, "child<", NULL)) {
1486 continue;
1487 }
1488
1489 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1490 if (found) {
1491 if (dev) {
1492 if (ambiguous) {
1493 *ambiguous = true;
1494 }
1495 return NULL;
1496 }
1497 dev = found;
1498 }
1499
1500 if (ambiguous && *ambiguous) {
1501 return NULL;
1502 }
1503 }
1504
1505 return dev;
1506}
1507
1508DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1509{
1510 bool partial_path = true;
1511 DeviceState *dev;
1512 gchar **parts;
1513
1514 parts = g_strsplit(path, "/", 0);
1515 if (parts == NULL || parts[0] == NULL) {
1516 g_strfreev(parts);
1517 return qdev_get_root();
1518 }
1519
1520 if (strcmp(parts[0], "") == 0) {
1521 partial_path = false;
1522 }
1523
1524 if (partial_path) {
1525 if (ambiguous) {
1526 *ambiguous = false;
1527 }
1528 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1529 } else {
1530 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1531 }
1532
1533 g_strfreev(parts);
1534
1535 return dev;
1536}
1537
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001538typedef struct StringProperty
1539{
1540 char *(*get)(DeviceState *, Error **);
1541 void (*set)(DeviceState *, const char *, Error **);
1542} StringProperty;
1543
1544static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1545 const char *name, Error **errp)
1546{
1547 StringProperty *prop = opaque;
1548 char *value;
1549
1550 value = prop->get(dev, errp);
1551 if (value) {
1552 visit_type_str(v, &value, name, errp);
1553 g_free(value);
1554 }
1555}
1556
1557static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1558 const char *name, Error **errp)
1559{
1560 StringProperty *prop = opaque;
1561 char *value;
1562 Error *local_err = NULL;
1563
1564 visit_type_str(v, &value, name, &local_err);
1565 if (local_err) {
1566 error_propagate(errp, local_err);
1567 return;
1568 }
1569
1570 prop->set(dev, value, errp);
1571 g_free(value);
1572}
1573
1574static void qdev_property_release_str(DeviceState *dev, const char *name,
1575 void *opaque)
1576{
1577 StringProperty *prop = opaque;
1578 g_free(prop);
1579}
1580
1581void qdev_property_add_str(DeviceState *dev, const char *name,
1582 char *(*get)(DeviceState *, Error **),
1583 void (*set)(DeviceState *, const char *, Error **),
1584 Error **errp)
1585{
1586 StringProperty *prop = g_malloc0(sizeof(*prop));
1587
1588 prop->get = get;
1589 prop->set = set;
1590
1591 qdev_property_add(dev, name, "string",
1592 get ? qdev_property_get_str : NULL,
1593 set ? qdev_property_set_str : NULL,
1594 qdev_property_release_str,
1595 prop, errp);
1596}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001597
1598void qdev_machine_init(void)
1599{
1600 qdev_get_peripheral_anon();
1601 qdev_get_peripheral();
1602}
Anthony Liguori32fea402011-12-16 14:34:46 -06001603
Anthony Liguori94afdad2011-12-04 11:36:01 -06001604void device_reset(DeviceState *dev)
1605{
1606 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1607
1608 if (klass->reset) {
1609 klass->reset(dev);
1610 }
1611}
1612
Anthony Liguori32fea402011-12-16 14:34:46 -06001613static TypeInfo device_type_info = {
1614 .name = TYPE_DEVICE,
1615 .parent = TYPE_OBJECT,
1616 .instance_size = sizeof(DeviceState),
1617 .abstract = true,
1618 .class_size = sizeof(DeviceClass),
1619};
1620
1621static void init_qdev(void)
1622{
1623 type_register_static(&device_type_info);
1624}
1625
1626device_init(init_qdev);