blob: b273cd2cc3f25f178f563295b413281753f8a30d [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 Liguori6e008582011-12-09 11:06:57 -060051 DeviceInfo *info = data;
Anthony Liguori94afdad2011-12-04 11:36:01 -060052
Anthony Liguori6e008582011-12-09 11:06:57 -060053 dc->fw_name = info->fw_name;
54 dc->alias = info->alias;
55 dc->desc = info->desc;
56 dc->props = info->props;
57 dc->no_user = info->no_user;
Anthony Liguori94afdad2011-12-04 11:36:01 -060058
Anthony Liguori6e008582011-12-09 11:06:57 -060059 dc->reset = info->reset;
Anthony Liguori3dde52d2011-12-04 14:37:06 -060060
Anthony Liguori6e008582011-12-09 11:06:57 -060061 dc->vmsd = info->vmsd;
62
63 dc->init = info->init;
64 dc->unplug = info->unplug;
65 dc->exit = info->exit;
66 dc->bus_info = info->bus_info;
67
68 if (info->class_init) {
69 info->class_init(klass, data);
Anthony Liguori3dde52d2011-12-04 14:37:06 -060070 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060071}
72
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060073const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
74{
Anthony Liguori6e008582011-12-09 11:06:57 -060075 DeviceClass *dc = DEVICE_GET_CLASS(dev);
76 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060077}
78
79BusInfo *qdev_get_bus_info(DeviceState *dev)
80{
Anthony Liguori6e008582011-12-09 11:06:57 -060081 DeviceClass *dc = DEVICE_GET_CLASS(dev);
82 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060083}
84
85Property *qdev_get_props(DeviceState *dev)
86{
Anthony Liguori6e008582011-12-09 11:06:57 -060087 DeviceClass *dc = DEVICE_GET_CLASS(dev);
88 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060089}
90
91const char *qdev_fw_name(DeviceState *dev)
92{
Anthony Liguori6e008582011-12-09 11:06:57 -060093 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060094
Anthony Liguori6e008582011-12-09 11:06:57 -060095 if (dc->fw_name) {
96 return dc->fw_name;
97 } else if (dc->alias) {
98 return dc->alias;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060099 }
100
101 return object_get_typename(OBJECT(dev));
102}
103
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600104void qdev_register_subclass(DeviceInfo *info, const char *parent)
Paul Brookaae94602009-05-14 22:35:06 +0100105{
Anthony Liguori32fea402011-12-16 14:34:46 -0600106 TypeInfo type_info = {};
107
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +0200108 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +0200109 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +0100110
Anthony Liguori32fea402011-12-16 14:34:46 -0600111 type_info.name = info->name;
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600112 type_info.parent = parent;
Anthony Liguori32fea402011-12-16 14:34:46 -0600113 type_info.instance_size = info->size;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600114 type_info.class_init = qdev_subclass_init;
115 type_info.class_data = info;
Anthony Liguori32fea402011-12-16 14:34:46 -0600116
117 type_register_static(&type_info);
118
Gerd Hoffmann042f84d2009-06-30 14:12:09 +0200119 info->next = device_info_list;
120 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +0100121}
122
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600123void qdev_register(DeviceInfo *info)
124{
125 qdev_register_subclass(info, TYPE_DEVICE);
126}
127
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200128static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
129{
130 DeviceInfo *info;
131
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200132 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200133 for (info = device_info_list; info != NULL; info = info->next) {
134 if (bus_info && info->bus_info != bus_info)
135 continue;
136 if (strcmp(info->name, name) != 0)
137 continue;
138 return info;
139 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200140
141 /* failing that check the aliases */
142 for (info = device_info_list; info != NULL; info = info->next) {
143 if (bus_info && info->bus_info != bus_info)
144 continue;
145 if (!info->alias)
146 continue;
147 if (strcmp(info->alias, name) != 0)
148 continue;
149 return info;
150 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200151 return NULL;
152}
153
Blue Swirla369da52011-09-27 19:15:42 +0000154bool qdev_exists(const char *name)
155{
156 return !!qdev_find_info(NULL, name);
157}
Anthony Liguori40021f02011-12-04 12:22:06 -0600158
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100159static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
160 Error **errp);
161
Markus Armbruster0c175422010-02-19 19:12:18 +0100162static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +0100163{
Paul Brookaae94602009-05-14 22:35:06 +0100164 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600165 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100166
Markus Armbruster0c175422010-02-19 19:12:18 +0100167 assert(bus->info == info->bus_info);
Anthony Liguori32fea402011-12-16 14:34:46 -0600168 dev = DEVICE(object_new(info->name));
Paul Brook02e2da42009-05-23 00:05:19 +0100169 dev->parent_bus = bus;
Anthony Liguori6e008582011-12-09 11:06:57 -0600170 qdev_prop_set_defaults(dev, qdev_get_props(dev));
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200171 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100172 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200173 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200174 if (qdev_hotplug) {
175 assert(bus->allow_hotplug);
176 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700177 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200178 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200179 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600180 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200181 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600182
Anthony Liguori6e008582011-12-09 11:06:57 -0600183 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600184 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100185 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600186 }
187
Anthony Liguori6e008582011-12-09 11:06:57 -0600188 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600189 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100190 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600191 }
192
Anthony Liguoricd34d662011-12-12 14:29:43 -0600193 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
194
Paul Brookaae94602009-05-14 22:35:06 +0100195 return dev;
196}
197
Markus Armbruster0c175422010-02-19 19:12:18 +0100198/* Create a new device. This only initializes the device state structure
199 and allows properties to be set. qdev_init should be called to
200 initialize the actual device emulation. */
201DeviceState *qdev_create(BusState *bus, const char *name)
202{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000203 DeviceState *dev;
204
205 dev = qdev_try_create(bus, name);
206 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100207 if (bus) {
208 hw_error("Unknown device '%s' for bus '%s'\n", name,
209 bus->info->name);
210 } else {
211 hw_error("Unknown device '%s' for default sysbus\n", name);
212 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000213 }
214
215 return dev;
216}
217
218DeviceState *qdev_try_create(BusState *bus, const char *name)
219{
Markus Armbruster0c175422010-02-19 19:12:18 +0100220 DeviceInfo *info;
221
222 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100223 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100224 }
225
226 info = qdev_find_info(bus->info, name);
227 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000228 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100229 }
230
231 return qdev_create_from_info(bus, info);
232}
233
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100234static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200235{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100236 error_printf("name \"%s\", bus %s",
237 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200238 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100239 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200240 }
241 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100242 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200243 }
244 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100245 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200246 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100247 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200248}
249
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200250static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200251{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200252 DeviceState *dev = opaque;
253
254 if (strcmp(name, "driver") == 0)
255 return 0;
256 if (strcmp(name, "bus") == 0)
257 return 0;
258
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100259 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200260 return -1;
261 }
262 return 0;
263}
264
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100265int qdev_device_help(QemuOpts *opts)
266{
267 const char *driver;
268 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100269 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100270
271 driver = qemu_opt_get(opts, "driver");
272 if (driver && !strcmp(driver, "?")) {
273 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100274 if (info->no_user) {
275 continue; /* not available, don't show */
276 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100277 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100278 }
279 return 1;
280 }
281
Markus Armbruster542379f2011-11-08 11:00:38 +0100282 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100283 return 0;
284 }
285
286 info = qdev_find_info(NULL, driver);
287 if (!info) {
288 return 0;
289 }
290
291 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100292 /*
293 * TODO Properties without a parser are just for dirty hacks.
294 * qdev_prop_ptr is the only such PropertyInfo. It's marked
295 * for removal. This conditional should be removed along with
296 * it.
297 */
298 if (!prop->info->parse) {
299 continue; /* no way to set it, don't show */
300 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100301 error_printf("%s.%s=%s\n", info->name, prop->name,
302 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100303 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200304 for (prop = info->bus_info->props; prop && prop->name; prop++) {
305 if (!prop->info->parse) {
306 continue; /* no way to set it, don't show */
307 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100308 error_printf("%s.%s=%s\n", info->name, prop->name,
309 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200310 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100311 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100312}
313
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600314static DeviceState *qdev_get_peripheral(void)
315{
316 static DeviceState *dev;
317
318 if (dev == NULL) {
319 dev = qdev_create(NULL, "container");
320 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
321 qdev_init_nofail(dev);
322 }
323
324 return dev;
325}
326
Anthony Liguori8eb02832011-12-12 14:29:37 -0600327static DeviceState *qdev_get_peripheral_anon(void)
328{
329 static DeviceState *dev;
330
331 if (dev == NULL) {
332 dev = qdev_create(NULL, "container");
333 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
334 qdev_init_nofail(dev);
335 }
336
337 return dev;
338}
339
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200340DeviceState *qdev_device_add(QemuOpts *opts)
341{
342 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200343 DeviceInfo *info;
344 DeviceState *qdev;
345 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200346
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200347 driver = qemu_opt_get(opts, "driver");
348 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100349 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200350 return NULL;
351 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200352
353 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200354 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100355 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100356 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100357 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200358 return NULL;
359 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200360
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200361 /* find bus */
362 path = qemu_opt_get(opts, "bus");
363 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200364 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100365 if (!bus) {
366 return NULL;
367 }
368 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100369 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
370 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100371 return NULL;
372 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200373 } else {
374 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100375 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100376 qerror_report(QERR_NO_BUS_FOR_DEVICE,
377 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100378 return NULL;
379 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200380 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200381 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100382 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200383 return NULL;
384 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200385
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200386 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100387 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200388 id = qemu_opts_id(opts);
389 if (id) {
390 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600391 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600392 } else {
393 static int anon_count;
394 gchar *name = g_strdup_printf("device[%d]", anon_count++);
395 qdev_property_add_child(qdev_get_peripheral_anon(), name,
396 qdev, NULL);
397 g_free(name);
398 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200399 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
400 qdev_free(qdev);
401 return NULL;
402 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200403 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100404 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200405 return NULL;
406 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200407 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200408 return qdev;
409}
410
Paul Brookaae94602009-05-14 22:35:06 +0100411/* Initialize a device. Device properties should be set before calling
412 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200413 calling this function.
414 On failure, destroy the device and return negative value.
415 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200416int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100417{
Anthony Liguori6e008582011-12-09 11:06:57 -0600418 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200419 int rc;
420
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200421 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600422
423 /* FIXME hopefully this doesn't break anything */
424 rc = dc->init(dev, NULL);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200425 if (rc < 0) {
426 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200427 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200428 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600429 if (qdev_get_vmsd(dev)) {
430 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200431 dev->instance_id_alias,
432 dev->alias_required_for_version);
433 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200434 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600435 if (dev->hotplugged) {
436 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200437 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200438 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100439}
440
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200441void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
442 int required_for_version)
443{
444 assert(dev->state == DEV_STATE_CREATED);
445 dev->instance_id_alias = alias_id;
446 dev->alias_required_for_version = required_for_version;
447}
448
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200449int qdev_unplug(DeviceState *dev)
450{
Anthony Liguori6e008582011-12-09 11:06:57 -0600451 DeviceClass *dc = DEVICE_GET_CLASS(dev);
452
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200453 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100454 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200455 return -1;
456 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600457 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530458
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700459 qdev_hot_removed = true;
460
Anthony Liguori6e008582011-12-09 11:06:57 -0600461 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200462}
463
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900464static int qdev_reset_one(DeviceState *dev, void *opaque)
465{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600466 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900467
468 return 0;
469}
470
471BusState *sysbus_get_default(void)
472{
Stefan Weil68694892010-12-16 19:33:22 +0100473 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900474 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100475 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900476 return main_system_bus;
477}
478
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900479static int qbus_reset_one(BusState *bus, void *opaque)
480{
481 if (bus->info->reset) {
482 return bus->info->reset(bus);
483 }
484 return 0;
485}
486
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900487void qdev_reset_all(DeviceState *dev)
488{
489 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
490}
491
Isaku Yamahata80376c32010-12-20 14:33:35 +0900492void qbus_reset_all_fn(void *opaque)
493{
494 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200495 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900496}
497
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200498/* can be used as ->unplug() callback for the simple cases */
499int qdev_simple_unplug_cb(DeviceState *dev)
500{
501 /* just zap it */
502 qdev_free(dev);
503 return 0;
504}
505
Michael Tokarev3b29a102011-04-06 17:51:59 +0400506
507/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200508 returning an error value. This is okay during machine creation.
509 Don't use for hotplug, because there callers need to recover from
510 failure. Exception: if you know the device's init() callback can't
511 fail, then qdev_init_nofail() can't fail either, and is therefore
512 usable even then. But relying on the device implementation that
513 way is somewhat unclean, and best avoided. */
514void qdev_init_nofail(DeviceState *dev)
515{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200516 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600517 error_report("Initialization of device %s failed",
518 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200519 exit(1);
520 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200521}
522
Anthony Liguori44677de2011-12-12 14:29:26 -0600523static void qdev_property_del_all(DeviceState *dev)
524{
525 while (!QTAILQ_EMPTY(&dev->properties)) {
526 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
527
528 QTAILQ_REMOVE(&dev->properties, prop, node);
529
530 if (prop->release) {
531 prop->release(dev, prop->name, prop->opaque);
532 }
533
534 g_free(prop->name);
535 g_free(prop->type);
536 g_free(prop);
537 }
538}
539
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600540static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
541{
542 DeviceProperty *prop;
543
544 QTAILQ_FOREACH(prop, &dev->properties, node) {
545 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
546 break;
547 }
548 }
549
550 g_assert(prop != NULL);
551
552 QTAILQ_REMOVE(&dev->properties, prop, node);
553
554 if (prop->release) {
555 prop->release(dev, prop->name, prop->opaque);
556 }
557
558 g_free(prop->name);
559 g_free(prop->type);
560 g_free(prop);
561}
562
Paul Brook02e2da42009-05-23 00:05:19 +0100563/* Unlink device from bus and free the structure. */
564void qdev_free(DeviceState *dev)
565{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200566 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200567 Property *prop;
Anthony Liguori6e008582011-12-09 11:06:57 -0600568 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200569
Anthony Liguori44677de2011-12-12 14:29:26 -0600570 qdev_property_del_all(dev);
571
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200572 if (dev->state == DEV_STATE_INITIALIZED) {
573 while (dev->num_child_bus) {
574 bus = QLIST_FIRST(&dev->child_bus);
575 qbus_free(bus);
576 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600577 if (qdev_get_vmsd(dev)) {
578 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
579 }
580 if (dc->exit) {
581 dc->exit(dev);
582 }
583 if (dev->opts) {
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200584 qemu_opts_del(dev->opts);
Anthony Liguori6e008582011-12-09 11:06:57 -0600585 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200586 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200587 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori6e008582011-12-09 11:06:57 -0600588 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200589 if (prop->info->free) {
590 prop->info->free(dev, prop);
591 }
592 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600593 if (dev->parent) {
594 qdev_property_del_child(dev->parent, dev, NULL);
595 }
596 if (dev->ref != 0) {
597 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
598 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600599 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100600}
601
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200602void qdev_machine_creation_done(void)
603{
604 /*
605 * ok, initial machine setup is done, starting from now we can
606 * only create hotpluggable devices
607 */
608 qdev_hotplug = 1;
609}
610
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700611bool qdev_machine_modified(void)
612{
613 return qdev_hot_added || qdev_hot_removed;
614}
615
Paul Brookaae94602009-05-14 22:35:06 +0100616/* Get a character (serial) device interface. */
617CharDriverState *qdev_init_chardev(DeviceState *dev)
618{
619 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530620
621 /* FIXME: This function needs to go away: use chardev properties! */
622 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100623}
624
Paul Brook02e2da42009-05-23 00:05:19 +0100625BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100626{
Paul Brook02e2da42009-05-23 00:05:19 +0100627 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100628}
629
Paul Brookaae94602009-05-14 22:35:06 +0100630void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
631{
632 assert(dev->num_gpio_in == 0);
633 dev->num_gpio_in = n;
634 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
635}
636
637void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
638{
639 assert(dev->num_gpio_out == 0);
640 dev->num_gpio_out = n;
641 dev->gpio_out = pins;
642}
643
644qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
645{
646 assert(n >= 0 && n < dev->num_gpio_in);
647 return dev->gpio_in[n];
648}
649
650void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
651{
652 assert(n >= 0 && n < dev->num_gpio_out);
653 dev->gpio_out[n] = pin;
654}
655
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200656void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
657{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200658 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200659 if (nd->vlan)
660 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
661 if (nd->netdev)
662 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530663 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200664 qdev_prop_exists(dev, "vectors")) {
665 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
666 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100667 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200668}
669
Paul Brook02e2da42009-05-23 00:05:19 +0100670BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100671{
Paul Brook02e2da42009-05-23 00:05:19 +0100672 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100673
Blue Swirl72cf2d42009-09-12 07:36:22 +0000674 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100675 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100676 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100677 }
678 }
679 return NULL;
680}
681
Anthony Liguori81699d82010-11-19 18:55:58 +0900682int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
683 qbus_walkerfn *busfn, void *opaque)
684{
685 DeviceState *dev;
686 int err;
687
688 if (busfn) {
689 err = busfn(bus, opaque);
690 if (err) {
691 return err;
692 }
693 }
694
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200695 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900696 err = qdev_walk_children(dev, devfn, busfn, opaque);
697 if (err < 0) {
698 return err;
699 }
700 }
701
702 return 0;
703}
704
705int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
706 qbus_walkerfn *busfn, void *opaque)
707{
708 BusState *bus;
709 int err;
710
711 if (devfn) {
712 err = devfn(dev, opaque);
713 if (err) {
714 return err;
715 }
716 }
717
718 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
719 err = qbus_walk_children(bus, devfn, busfn, opaque);
720 if (err < 0) {
721 return err;
722 }
723 }
724
725 return 0;
726}
727
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200728static BusState *qbus_find_recursive(BusState *bus, const char *name,
729 const BusInfo *info)
730{
731 DeviceState *dev;
732 BusState *child, *ret;
733 int match = 1;
734
735 if (name && (strcmp(bus->name, name) != 0)) {
736 match = 0;
737 }
738 if (info && (bus->info != info)) {
739 match = 0;
740 }
741 if (match) {
742 return bus;
743 }
744
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200745 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000746 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200747 ret = qbus_find_recursive(child, name, info);
748 if (ret) {
749 return ret;
750 }
751 }
752 }
753 return NULL;
754}
755
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900756DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200757{
758 DeviceState *dev, *ret;
759 BusState *child;
760
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200761 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200762 if (dev->id && strcmp(dev->id, id) == 0)
763 return dev;
764 QLIST_FOREACH(child, &dev->child_bus, sibling) {
765 ret = qdev_find_recursive(child, id);
766 if (ret) {
767 return ret;
768 }
769 }
770 }
771 return NULL;
772}
773
Markus Armbruster53db16b2010-02-18 18:55:59 +0100774static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200775{
776 BusState *child;
777 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200778
Markus Armbruster53db16b2010-02-18 18:55:59 +0100779 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600780 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000781 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100782 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200783 sep = ", ";
784 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100785 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200786}
787
Markus Armbruster53db16b2010-02-18 18:55:59 +0100788static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200789{
790 DeviceState *dev;
791 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200792
Markus Armbruster53db16b2010-02-18 18:55:59 +0100793 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200794 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600795 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200796 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100797 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200798 sep = ", ";
799 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100800 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200801}
802
803static BusState *qbus_find_bus(DeviceState *dev, char *elem)
804{
805 BusState *child;
806
Blue Swirl72cf2d42009-09-12 07:36:22 +0000807 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200808 if (strcmp(child->name, elem) == 0) {
809 return child;
810 }
811 }
812 return NULL;
813}
814
815static DeviceState *qbus_find_dev(BusState *bus, char *elem)
816{
817 DeviceState *dev;
818
819 /*
820 * try to match in order:
821 * (1) instance id, if present
822 * (2) driver name
823 * (3) driver alias, if present
824 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200825 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200826 if (dev->id && strcmp(dev->id, elem) == 0) {
827 return dev;
828 }
829 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200830 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600831 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200832 return dev;
833 }
834 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200835 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600836 DeviceClass *dc = DEVICE_GET_CLASS(dev);
837
838 if (dc->alias && strcmp(dc->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200839 return dev;
840 }
841 }
842 return NULL;
843}
844
845static BusState *qbus_find(const char *path)
846{
847 DeviceState *dev;
848 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100849 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200850 int pos, len;
851
852 /* find start element */
853 if (path[0] == '/') {
854 bus = main_system_bus;
855 pos = 0;
856 } else {
857 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100858 assert(!path[0]);
859 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200860 }
861 bus = qbus_find_recursive(main_system_bus, elem, NULL);
862 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100863 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200864 return NULL;
865 }
866 pos = len;
867 }
868
869 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100870 assert(path[pos] == '/' || !path[pos]);
871 while (path[pos] == '/') {
872 pos++;
873 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200874 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200875 return bus;
876 }
877
878 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100879 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
880 assert(0);
881 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200882 }
883 pos += len;
884 dev = qbus_find_dev(bus, elem);
885 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100886 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100887 if (!monitor_cur_is_qmp()) {
888 qbus_list_dev(bus);
889 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200890 return NULL;
891 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100892
893 assert(path[pos] == '/' || !path[pos]);
894 while (path[pos] == '/') {
895 pos++;
896 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200897 if (path[pos] == '\0') {
898 /* last specified element is a device. If it has exactly
899 * one child bus accept it nevertheless */
900 switch (dev->num_child_bus) {
901 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100902 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200903 return NULL;
904 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000905 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200906 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100907 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100908 if (!monitor_cur_is_qmp()) {
909 qbus_list_bus(dev);
910 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200911 return NULL;
912 }
913 }
914
915 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100916 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
917 assert(0);
918 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200919 }
920 pos += len;
921 bus = qbus_find_bus(dev, elem);
922 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100923 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100924 if (!monitor_cur_is_qmp()) {
925 qbus_list_bus(dev);
926 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200927 return NULL;
928 }
929 }
930}
931
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200932void qbus_create_inplace(BusState *bus, BusInfo *info,
933 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100934{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200935 char *buf;
936 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100937
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200938 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100939 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200940
941 if (name) {
942 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500943 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200944 } else if (parent && parent->id) {
945 /* parent device has id -> use it for bus name */
946 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500947 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200948 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
949 bus->name = buf;
950 } else {
951 /* no id -> use lowercase bus type for bus name */
952 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500953 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200954 len = snprintf(buf, len, "%s.%d", info->name,
955 parent ? parent->num_child_bus : 0);
956 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200957 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200958 bus->name = buf;
959 }
960
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200961 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100962 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000963 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200964 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900965 } else if (bus != main_system_bus) {
966 /* TODO: once all bus devices are qdevified,
967 only reset handler for main_system_bus should be registered here. */
968 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100969 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200970}
971
972BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
973{
974 BusState *bus;
975
Anthony Liguori7267c092011-08-20 22:09:37 -0500976 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200977 bus->qdev_allocated = 1;
978 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100979 return bus;
980}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100981
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900982static void main_system_bus_create(void)
983{
984 /* assign main_system_bus before qbus_create_inplace()
985 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500986 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900987 main_system_bus->qdev_allocated = 1;
988 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
989 "main-system-bus");
990}
991
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200992void qbus_free(BusState *bus)
993{
994 DeviceState *dev;
995
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200996 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200997 qdev_free(dev);
998 }
999 if (bus->parent) {
1000 QLIST_REMOVE(bus, sibling);
1001 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +09001002 } else {
1003 assert(bus != main_system_bus); /* main_system_bus is never freed */
1004 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001005 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001006 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001007 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001008 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +02001009 }
1010}
1011
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001012#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
1013static void qbus_print(Monitor *mon, BusState *bus, int indent);
1014
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001015static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
1016 const char *prefix, int indent)
1017{
1018 char buf[64];
1019
1020 if (!props)
1021 return;
1022 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +01001023 /*
1024 * TODO Properties without a print method are just for dirty
1025 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1026 * marked for removal. The test props->info->print should be
1027 * removed along with it.
1028 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001029 if (props->info->print) {
1030 props->info->print(dev, props, buf, sizeof(buf));
1031 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1032 }
1033 props++;
1034 }
1035}
1036
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001037static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1038{
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001039 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001040 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +02001041 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001042 indent += 2;
1043 if (dev->num_gpio_in) {
1044 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1045 }
1046 if (dev->num_gpio_out) {
1047 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1048 }
Anthony Liguori6e008582011-12-09 11:06:57 -06001049 qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001050 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001051 if (dev->parent_bus->info->print_dev)
1052 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001053 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001054 qbus_print(mon, child, indent);
1055 }
1056}
1057
1058static void qbus_print(Monitor *mon, BusState *bus, int indent)
1059{
1060 struct DeviceState *dev;
1061
1062 qdev_printf("bus: %s\n", bus->name);
1063 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001064 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001065 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001066 qdev_print(mon, dev, indent);
1067 }
1068}
1069#undef qdev_printf
1070
1071void do_info_qtree(Monitor *mon)
1072{
1073 if (main_system_bus)
1074 qbus_print(mon, main_system_bus, 0);
1075}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001076
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001077void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001078{
1079 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001080
1081 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +01001082 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001083 }
1084}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001085
Markus Armbruster8bc27242010-02-10 20:52:01 +01001086int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001087{
1088 QemuOpts *opts;
1089
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001090 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001091 if (!opts) {
1092 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001093 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001094 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1095 qemu_opts_del(opts);
1096 return 0;
1097 }
1098 if (!qdev_device_add(opts)) {
1099 qemu_opts_del(opts);
1100 return -1;
1101 }
1102 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001103}
1104
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001105int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001106{
1107 const char *id = qdict_get_str(qdict, "id");
1108 DeviceState *dev;
1109
1110 dev = qdev_find_recursive(main_system_bus, id);
1111 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001112 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1113 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001114 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001115 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001116}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001117
1118static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1119{
1120 int l = 0;
1121
1122 if (dev && dev->parent_bus) {
1123 char *d;
1124 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1125 if (dev->parent_bus->info->get_fw_dev_path) {
1126 d = dev->parent_bus->info->get_fw_dev_path(dev);
1127 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001128 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001129 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001130 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001131 }
1132 }
1133 l += snprintf(p + l , size - l, "/");
1134
1135 return l;
1136}
1137
1138char* qdev_get_fw_dev_path(DeviceState *dev)
1139{
1140 char path[128];
1141 int l;
1142
1143 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1144
1145 path[l-1] = '\0';
1146
1147 return strdup(path);
1148}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001149
Anthony Liguoricd34d662011-12-12 14:29:43 -06001150char *qdev_get_type(DeviceState *dev, Error **errp)
1151{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001152 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001153}
1154
Anthony Liguori85ed3032011-12-12 14:29:25 -06001155void qdev_ref(DeviceState *dev)
1156{
1157 dev->ref++;
1158}
1159
1160void qdev_unref(DeviceState *dev)
1161{
1162 g_assert(dev->ref > 0);
1163 dev->ref--;
1164}
Anthony Liguori44677de2011-12-12 14:29:26 -06001165
1166void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1167 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1168 DevicePropertyRelease *release,
1169 void *opaque, Error **errp)
1170{
1171 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1172
1173 prop->name = g_strdup(name);
1174 prop->type = g_strdup(type);
1175
1176 prop->get = get;
1177 prop->set = set;
1178 prop->release = release;
1179 prop->opaque = opaque;
1180
1181 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1182}
1183
1184static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1185{
1186 DeviceProperty *prop;
1187
1188 QTAILQ_FOREACH(prop, &dev->properties, node) {
1189 if (strcmp(prop->name, name) == 0) {
1190 return prop;
1191 }
1192 }
1193
1194 return NULL;
1195}
1196
1197void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1198 Error **errp)
1199{
1200 DeviceProperty *prop = qdev_property_find(dev, name);
1201
1202 if (prop == NULL) {
1203 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1204 return;
1205 }
1206
1207 if (!prop->get) {
1208 error_set(errp, QERR_PERMISSION_DENIED);
1209 } else {
1210 prop->get(dev, v, prop->opaque, name, errp);
1211 }
1212}
1213
1214void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1215 Error **errp)
1216{
1217 DeviceProperty *prop = qdev_property_find(dev, name);
1218
1219 if (prop == NULL) {
1220 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1221 return;
1222 }
1223
1224 if (!prop->set) {
1225 error_set(errp, QERR_PERMISSION_DENIED);
1226 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001227 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001228 }
1229}
1230
1231const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1232{
1233 DeviceProperty *prop = qdev_property_find(dev, name);
1234
1235 if (prop == NULL) {
1236 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1237 return NULL;
1238 }
1239
1240 return prop->type;
1241}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001242
1243/**
1244 * Legacy property handling
1245 */
1246
1247static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1248 const char *name, Error **errp)
1249{
1250 Property *prop = opaque;
1251
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001252 char buffer[1024];
1253 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001254
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001255 prop->info->print(dev, prop, buffer, sizeof(buffer));
1256 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001257}
1258
1259static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1260 const char *name, Error **errp)
1261{
1262 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001263 Error *local_err = NULL;
1264 char *ptr = NULL;
1265 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001266
1267 if (dev->state != DEV_STATE_CREATED) {
1268 error_set(errp, QERR_PERMISSION_DENIED);
1269 return;
1270 }
1271
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001272 visit_type_str(v, &ptr, name, &local_err);
1273 if (local_err) {
1274 error_propagate(errp, local_err);
1275 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001276 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001277
1278 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001279 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001280 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001281}
1282
1283/**
1284 * @qdev_add_legacy_property - adds a legacy property
1285 *
1286 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001287 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001288 *
1289 * Legacy properties are always processed as strings. The format of the string
1290 * depends on the property type.
1291 */
1292void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1293 Error **errp)
1294{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001295 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001296
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001297 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001298 type = g_strdup_printf("legacy<%s>",
1299 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001300
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001301 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001302 prop->info->print ? qdev_get_legacy_property : NULL,
1303 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001304 NULL,
1305 prop, errp);
1306
1307 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001308 g_free(name);
1309}
1310
1311/**
1312 * @qdev_property_add_static - add a @Property to a device.
1313 *
1314 * Static properties access data in a struct. The actual type of the
1315 * property and the field depends on the property type.
1316 */
1317void qdev_property_add_static(DeviceState *dev, Property *prop,
1318 Error **errp)
1319{
1320 qdev_property_add(dev, prop->name, prop->info->name,
1321 prop->info->get, prop->info->set,
1322 NULL,
1323 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001324}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001325
1326DeviceState *qdev_get_root(void)
1327{
1328 static DeviceState *qdev_root;
1329
1330 if (!qdev_root) {
1331 qdev_root = qdev_create(NULL, "container");
1332 qdev_init_nofail(qdev_root);
1333 }
1334
1335 return qdev_root;
1336}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001337
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001338static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1339 const char *name, Error **errp)
1340{
1341 DeviceState *child = opaque;
1342 gchar *path;
1343
1344 path = qdev_get_canonical_path(child);
1345 visit_type_str(v, &path, name, errp);
1346 g_free(path);
1347}
1348
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001349static void qdev_release_child_property(DeviceState *dev, const char *name,
1350 void *opaque)
1351{
1352 DeviceState *child = opaque;
1353
1354 qdev_unref(child);
1355}
1356
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001357void qdev_property_add_child(DeviceState *dev, const char *name,
1358 DeviceState *child, Error **errp)
1359{
1360 gchar *type;
1361
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001362 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001363
1364 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001365 NULL, qdev_release_child_property,
1366 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001367
1368 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001369 g_assert(child->parent == NULL);
1370 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001371
1372 g_free(type);
1373}
1374
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001375static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1376 const char *name, Error **errp)
1377{
1378 DeviceState **child = opaque;
1379 gchar *path;
1380
1381 if (*child) {
1382 path = qdev_get_canonical_path(*child);
1383 visit_type_str(v, &path, name, errp);
1384 g_free(path);
1385 } else {
1386 path = (gchar *)"";
1387 visit_type_str(v, &path, name, errp);
1388 }
1389}
1390
1391static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1392 const char *name, Error **errp)
1393{
1394 DeviceState **child = opaque;
1395 bool ambiguous = false;
1396 const char *type;
1397 char *path;
1398
1399 type = qdev_property_get_type(dev, name, NULL);
1400
1401 visit_type_str(v, &path, name, errp);
1402
1403 if (*child) {
1404 qdev_unref(*child);
1405 }
1406
1407 if (strcmp(path, "") != 0) {
1408 DeviceState *target;
1409
1410 target = qdev_resolve_path(path, &ambiguous);
1411 if (target) {
1412 gchar *target_type;
1413
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001414 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001415 if (strcmp(target_type, type) == 0) {
1416 *child = target;
1417 qdev_ref(target);
1418 } else {
1419 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1420 }
1421
1422 g_free(target_type);
1423 } else {
1424 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1425 }
1426 } else {
1427 *child = NULL;
1428 }
1429
1430 g_free(path);
1431}
1432
1433void qdev_property_add_link(DeviceState *dev, const char *name,
1434 const char *type, DeviceState **child,
1435 Error **errp)
1436{
1437 gchar *full_type;
1438
1439 full_type = g_strdup_printf("link<%s>", type);
1440
1441 qdev_property_add(dev, name, full_type,
1442 qdev_get_link_property,
1443 qdev_set_link_property,
1444 NULL, child, errp);
1445
1446 g_free(full_type);
1447}
1448
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001449gchar *qdev_get_canonical_path(DeviceState *dev)
1450{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001451 DeviceState *root = qdev_get_root();
1452 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001453
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001454 while (dev != root) {
1455 DeviceProperty *prop = NULL;
1456
1457 g_assert(dev->parent != NULL);
1458
1459 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1460 if (!strstart(prop->type, "child<", NULL)) {
1461 continue;
1462 }
1463
1464 if (prop->opaque == dev) {
1465 if (path) {
1466 newpath = g_strdup_printf("%s/%s", prop->name, path);
1467 g_free(path);
1468 path = newpath;
1469 } else {
1470 path = g_strdup(prop->name);
1471 }
1472 break;
1473 }
1474 }
1475
1476 g_assert(prop != NULL);
1477
1478 dev = dev->parent;
1479 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001480
1481 newpath = g_strdup_printf("/%s", path);
1482 g_free(path);
1483
1484 return newpath;
1485}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001486
1487static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1488 gchar **parts,
1489 int index)
1490{
1491 DeviceProperty *prop;
1492 DeviceState *child;
1493
1494 if (parts[index] == NULL) {
1495 return parent;
1496 }
1497
1498 if (strcmp(parts[index], "") == 0) {
1499 return qdev_resolve_abs_path(parent, parts, index + 1);
1500 }
1501
1502 prop = qdev_property_find(parent, parts[index]);
1503 if (prop == NULL) {
1504 return NULL;
1505 }
1506
1507 child = NULL;
1508 if (strstart(prop->type, "link<", NULL)) {
1509 DeviceState **pchild = prop->opaque;
1510 if (*pchild) {
1511 child = *pchild;
1512 }
1513 } else if (strstart(prop->type, "child<", NULL)) {
1514 child = prop->opaque;
1515 }
1516
1517 if (!child) {
1518 return NULL;
1519 }
1520
1521 return qdev_resolve_abs_path(child, parts, index + 1);
1522}
1523
1524static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1525 gchar **parts,
1526 bool *ambiguous)
1527{
1528 DeviceState *dev;
1529 DeviceProperty *prop;
1530
1531 dev = qdev_resolve_abs_path(parent, parts, 0);
1532
1533 QTAILQ_FOREACH(prop, &parent->properties, node) {
1534 DeviceState *found;
1535
1536 if (!strstart(prop->type, "child<", NULL)) {
1537 continue;
1538 }
1539
1540 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1541 if (found) {
1542 if (dev) {
1543 if (ambiguous) {
1544 *ambiguous = true;
1545 }
1546 return NULL;
1547 }
1548 dev = found;
1549 }
1550
1551 if (ambiguous && *ambiguous) {
1552 return NULL;
1553 }
1554 }
1555
1556 return dev;
1557}
1558
1559DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1560{
1561 bool partial_path = true;
1562 DeviceState *dev;
1563 gchar **parts;
1564
1565 parts = g_strsplit(path, "/", 0);
1566 if (parts == NULL || parts[0] == NULL) {
1567 g_strfreev(parts);
1568 return qdev_get_root();
1569 }
1570
1571 if (strcmp(parts[0], "") == 0) {
1572 partial_path = false;
1573 }
1574
1575 if (partial_path) {
1576 if (ambiguous) {
1577 *ambiguous = false;
1578 }
1579 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1580 } else {
1581 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1582 }
1583
1584 g_strfreev(parts);
1585
1586 return dev;
1587}
1588
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001589typedef struct StringProperty
1590{
1591 char *(*get)(DeviceState *, Error **);
1592 void (*set)(DeviceState *, const char *, Error **);
1593} StringProperty;
1594
1595static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1596 const char *name, Error **errp)
1597{
1598 StringProperty *prop = opaque;
1599 char *value;
1600
1601 value = prop->get(dev, errp);
1602 if (value) {
1603 visit_type_str(v, &value, name, errp);
1604 g_free(value);
1605 }
1606}
1607
1608static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1609 const char *name, Error **errp)
1610{
1611 StringProperty *prop = opaque;
1612 char *value;
1613 Error *local_err = NULL;
1614
1615 visit_type_str(v, &value, name, &local_err);
1616 if (local_err) {
1617 error_propagate(errp, local_err);
1618 return;
1619 }
1620
1621 prop->set(dev, value, errp);
1622 g_free(value);
1623}
1624
1625static void qdev_property_release_str(DeviceState *dev, const char *name,
1626 void *opaque)
1627{
1628 StringProperty *prop = opaque;
1629 g_free(prop);
1630}
1631
1632void qdev_property_add_str(DeviceState *dev, const char *name,
1633 char *(*get)(DeviceState *, Error **),
1634 void (*set)(DeviceState *, const char *, Error **),
1635 Error **errp)
1636{
1637 StringProperty *prop = g_malloc0(sizeof(*prop));
1638
1639 prop->get = get;
1640 prop->set = set;
1641
1642 qdev_property_add(dev, name, "string",
1643 get ? qdev_property_get_str : NULL,
1644 set ? qdev_property_set_str : NULL,
1645 qdev_property_release_str,
1646 prop, errp);
1647}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001648
1649void qdev_machine_init(void)
1650{
1651 qdev_get_peripheral_anon();
1652 qdev_get_peripheral();
1653}
Anthony Liguori32fea402011-12-16 14:34:46 -06001654
Anthony Liguori94afdad2011-12-04 11:36:01 -06001655void device_reset(DeviceState *dev)
1656{
1657 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1658
1659 if (klass->reset) {
1660 klass->reset(dev);
1661 }
1662}
1663
Anthony Liguori32fea402011-12-16 14:34:46 -06001664static TypeInfo device_type_info = {
1665 .name = TYPE_DEVICE,
1666 .parent = TYPE_OBJECT,
1667 .instance_size = sizeof(DeviceState),
1668 .abstract = true,
1669 .class_size = sizeof(DeviceClass),
1670};
1671
1672static void init_qdev(void)
1673{
1674 type_register_static(&device_type_info);
1675}
1676
1677device_init(init_qdev);