blob: 18c587641a99e9073c7758d6c19969f227e80ccf [file] [log] [blame]
Paul Brookaae94602009-05-14 22:35:06 +01001/*
2 * Dynamic device configuration and creation.
3 *
4 * Copyright (c) 2009 CodeSourcery
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Paul Brookaae94602009-05-14 22:35:06 +010018 */
19
20/* The theory here is that it should be possible to create a machine without
21 knowledge of specific devices. Historically board init routines have
22 passed a bunch of arguments to each device, requiring the board know
23 exactly which device it is dealing with. This file provides an abstract
24 API for device configuration and initialization. Devices will generally
25 inherit from a particular bus (e.g. PCI or I2C) rather than
26 this API directly. */
27
Paul Brook9d07d752009-05-14 22:35:07 +010028#include "net.h"
Paul Brookaae94602009-05-14 22:35:06 +010029#include "qdev.h"
30#include "sysemu.h"
Gerd Hoffmanncae49562009-06-05 15:53:17 +010031#include "monitor.h"
Paul Brookaae94602009-05-14 22:35:06 +010032
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020033static int qdev_hotplug = 0;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070034static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020036
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020037/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000038static BusState *main_system_bus;
Isaku Yamahata2da8bb92011-08-02 10:59:13 +090039static void main_system_bus_create(void);
Paul Brook4d6ae672009-05-14 22:35:06 +010040
Gerd Hoffmann0958b4c2009-10-26 15:56:45 +010041DeviceInfo *device_info_list;
Paul Brookaae94602009-05-14 22:35:06 +010042
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020043static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 const BusInfo *info);
45static BusState *qbus_find(const char *path);
46
Paul Brookaae94602009-05-14 22:35:06 +010047/* Register a new device type. */
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060048static void qdev_subclass_init(ObjectClass *klass, void *data)
49{
50 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori94afdad2011-12-04 11:36:01 -060051
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060052 dc->info = data;
Anthony Liguori94afdad2011-12-04 11:36:01 -060053 dc->reset = dc->info->reset;
54
55 /* Poison to try to detect future uses */
56 dc->info->reset = NULL;
Anthony Liguori3dde52d2011-12-04 14:37:06 -060057
58 if (dc->info->class_init) {
59 dc->info->class_init(klass, data);
60 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060061}
62
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060063static DeviceInfo *qdev_get_info(DeviceState *dev)
Anthony Liguori30fbb9f2011-12-04 11:08:36 -060064{
65 return DEVICE_GET_CLASS(dev)->info;
66}
67
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060068const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
69{
70 return qdev_get_info(dev)->vmsd;
71}
72
73BusInfo *qdev_get_bus_info(DeviceState *dev)
74{
75 return qdev_get_info(dev)->bus_info;
76}
77
78Property *qdev_get_props(DeviceState *dev)
79{
80 return qdev_get_info(dev)->props;
81}
82
83const char *qdev_fw_name(DeviceState *dev)
84{
85 DeviceInfo *info = qdev_get_info(dev);
86
87 if (info->fw_name) {
88 return info->fw_name;
89 } else if (info->alias) {
90 return info->alias;
91 }
92
93 return object_get_typename(OBJECT(dev));
94}
95
Anthony Liguori3cc90eb2011-12-15 14:40:29 -060096void qdev_register_subclass(DeviceInfo *info, const char *parent)
Paul Brookaae94602009-05-14 22:35:06 +010097{
Anthony Liguori32fea402011-12-16 14:34:46 -060098 TypeInfo type_info = {};
99
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +0200100 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +0200101 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +0100102
Anthony Liguori32fea402011-12-16 14:34:46 -0600103 type_info.name = info->name;
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600104 type_info.parent = parent;
Anthony Liguori32fea402011-12-16 14:34:46 -0600105 type_info.instance_size = info->size;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600106 type_info.class_init = qdev_subclass_init;
107 type_info.class_data = info;
Anthony Liguori32fea402011-12-16 14:34:46 -0600108
109 type_register_static(&type_info);
110
Gerd Hoffmann042f84d2009-06-30 14:12:09 +0200111 info->next = device_info_list;
112 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +0100113}
114
Anthony Liguori3cc90eb2011-12-15 14:40:29 -0600115void qdev_register(DeviceInfo *info)
116{
117 qdev_register_subclass(info, TYPE_DEVICE);
118}
119
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200120static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
121{
122 DeviceInfo *info;
123
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200124 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200125 for (info = device_info_list; info != NULL; info = info->next) {
126 if (bus_info && info->bus_info != bus_info)
127 continue;
128 if (strcmp(info->name, name) != 0)
129 continue;
130 return info;
131 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +0200132
133 /* failing that check the aliases */
134 for (info = device_info_list; info != NULL; info = info->next) {
135 if (bus_info && info->bus_info != bus_info)
136 continue;
137 if (!info->alias)
138 continue;
139 if (strcmp(info->alias, name) != 0)
140 continue;
141 return info;
142 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +0200143 return NULL;
144}
145
Blue Swirla369da52011-09-27 19:15:42 +0000146bool qdev_exists(const char *name)
147{
148 return !!qdev_find_info(NULL, name);
149}
Anthony Liguori40021f02011-12-04 12:22:06 -0600150
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100151static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
152 Error **errp);
153
Markus Armbruster0c175422010-02-19 19:12:18 +0100154static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +0100155{
Paul Brookaae94602009-05-14 22:35:06 +0100156 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600157 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100158
Markus Armbruster0c175422010-02-19 19:12:18 +0100159 assert(bus->info == info->bus_info);
Anthony Liguori32fea402011-12-16 14:34:46 -0600160 dev = DEVICE(object_new(info->name));
Paul Brook02e2da42009-05-23 00:05:19 +0100161 dev->parent_bus = bus;
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600162 qdev_prop_set_defaults(dev, qdev_get_info(dev)->props);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200163 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100164 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200165 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200166 if (qdev_hotplug) {
167 assert(bus->allow_hotplug);
168 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700169 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200170 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200171 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600172 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200173 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600174
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600175 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600176 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100177 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600178 }
179
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600180 for (prop = qdev_get_info(dev)->bus_info->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600181 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100182 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600183 }
184
Anthony Liguoricd34d662011-12-12 14:29:43 -0600185 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
186
Paul Brookaae94602009-05-14 22:35:06 +0100187 return dev;
188}
189
Markus Armbruster0c175422010-02-19 19:12:18 +0100190/* Create a new device. This only initializes the device state structure
191 and allows properties to be set. qdev_init should be called to
192 initialize the actual device emulation. */
193DeviceState *qdev_create(BusState *bus, const char *name)
194{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000195 DeviceState *dev;
196
197 dev = qdev_try_create(bus, name);
198 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100199 if (bus) {
200 hw_error("Unknown device '%s' for bus '%s'\n", name,
201 bus->info->name);
202 } else {
203 hw_error("Unknown device '%s' for default sysbus\n", name);
204 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000205 }
206
207 return dev;
208}
209
210DeviceState *qdev_try_create(BusState *bus, const char *name)
211{
Markus Armbruster0c175422010-02-19 19:12:18 +0100212 DeviceInfo *info;
213
214 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100215 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100216 }
217
218 info = qdev_find_info(bus->info, name);
219 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000220 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100221 }
222
223 return qdev_create_from_info(bus, info);
224}
225
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100226static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200227{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100228 error_printf("name \"%s\", bus %s",
229 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200230 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100231 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200232 }
233 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100234 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200235 }
236 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100237 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200238 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100239 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200240}
241
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200242static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200243{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200244 DeviceState *dev = opaque;
245
246 if (strcmp(name, "driver") == 0)
247 return 0;
248 if (strcmp(name, "bus") == 0)
249 return 0;
250
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100251 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200252 return -1;
253 }
254 return 0;
255}
256
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100257int qdev_device_help(QemuOpts *opts)
258{
259 const char *driver;
260 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100261 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100262
263 driver = qemu_opt_get(opts, "driver");
264 if (driver && !strcmp(driver, "?")) {
265 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100266 if (info->no_user) {
267 continue; /* not available, don't show */
268 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100269 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100270 }
271 return 1;
272 }
273
Markus Armbruster542379f2011-11-08 11:00:38 +0100274 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100275 return 0;
276 }
277
278 info = qdev_find_info(NULL, driver);
279 if (!info) {
280 return 0;
281 }
282
283 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100284 /*
285 * TODO Properties without a parser are just for dirty hacks.
286 * qdev_prop_ptr is the only such PropertyInfo. It's marked
287 * for removal. This conditional should be removed along with
288 * it.
289 */
290 if (!prop->info->parse) {
291 continue; /* no way to set it, don't show */
292 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100293 error_printf("%s.%s=%s\n", info->name, prop->name,
294 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100295 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200296 for (prop = info->bus_info->props; prop && prop->name; prop++) {
297 if (!prop->info->parse) {
298 continue; /* no way to set it, don't show */
299 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100300 error_printf("%s.%s=%s\n", info->name, prop->name,
301 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200302 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100303 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100304}
305
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600306static DeviceState *qdev_get_peripheral(void)
307{
308 static DeviceState *dev;
309
310 if (dev == NULL) {
311 dev = qdev_create(NULL, "container");
312 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
313 qdev_init_nofail(dev);
314 }
315
316 return dev;
317}
318
Anthony Liguori8eb02832011-12-12 14:29:37 -0600319static DeviceState *qdev_get_peripheral_anon(void)
320{
321 static DeviceState *dev;
322
323 if (dev == NULL) {
324 dev = qdev_create(NULL, "container");
325 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
326 qdev_init_nofail(dev);
327 }
328
329 return dev;
330}
331
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200332DeviceState *qdev_device_add(QemuOpts *opts)
333{
334 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200335 DeviceInfo *info;
336 DeviceState *qdev;
337 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200338
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200339 driver = qemu_opt_get(opts, "driver");
340 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100341 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200342 return NULL;
343 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200344
345 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200346 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100347 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100348 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100349 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200350 return NULL;
351 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200352
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200353 /* find bus */
354 path = qemu_opt_get(opts, "bus");
355 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200356 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100357 if (!bus) {
358 return NULL;
359 }
360 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100361 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
362 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100363 return NULL;
364 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200365 } else {
366 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100367 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100368 qerror_report(QERR_NO_BUS_FOR_DEVICE,
369 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100370 return NULL;
371 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200372 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200373 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100374 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200375 return NULL;
376 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200377
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200378 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100379 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200380 id = qemu_opts_id(opts);
381 if (id) {
382 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600383 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600384 } else {
385 static int anon_count;
386 gchar *name = g_strdup_printf("device[%d]", anon_count++);
387 qdev_property_add_child(qdev_get_peripheral_anon(), name,
388 qdev, NULL);
389 g_free(name);
390 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200391 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
392 qdev_free(qdev);
393 return NULL;
394 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200395 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100396 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200397 return NULL;
398 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200399 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200400 return qdev;
401}
402
Paul Brookaae94602009-05-14 22:35:06 +0100403/* Initialize a device. Device properties should be set before calling
404 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200405 calling this function.
406 On failure, destroy the device and return negative value.
407 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200408int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100409{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200410 int rc;
411
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200412 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600413 rc = qdev_get_info(dev)->init(dev, qdev_get_info(dev));
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200414 if (rc < 0) {
415 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200416 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200417 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600418 if (qdev_get_info(dev)->vmsd) {
419 vmstate_register_with_alias_id(dev, -1, qdev_get_info(dev)->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200420 dev->instance_id_alias,
421 dev->alias_required_for_version);
422 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200423 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600424 if (dev->hotplugged) {
425 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200426 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200427 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100428}
429
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200430void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
431 int required_for_version)
432{
433 assert(dev->state == DEV_STATE_CREATED);
434 dev->instance_id_alias = alias_id;
435 dev->alias_required_for_version = required_for_version;
436}
437
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200438int qdev_unplug(DeviceState *dev)
439{
440 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100441 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200442 return -1;
443 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600444 assert(qdev_get_info(dev)->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530445
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700446 qdev_hot_removed = true;
447
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600448 return qdev_get_info(dev)->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200449}
450
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900451static int qdev_reset_one(DeviceState *dev, void *opaque)
452{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600453 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900454
455 return 0;
456}
457
458BusState *sysbus_get_default(void)
459{
Stefan Weil68694892010-12-16 19:33:22 +0100460 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900461 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100462 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900463 return main_system_bus;
464}
465
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900466static int qbus_reset_one(BusState *bus, void *opaque)
467{
468 if (bus->info->reset) {
469 return bus->info->reset(bus);
470 }
471 return 0;
472}
473
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900474void qdev_reset_all(DeviceState *dev)
475{
476 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
477}
478
Isaku Yamahata80376c32010-12-20 14:33:35 +0900479void qbus_reset_all_fn(void *opaque)
480{
481 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200482 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900483}
484
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200485/* can be used as ->unplug() callback for the simple cases */
486int qdev_simple_unplug_cb(DeviceState *dev)
487{
488 /* just zap it */
489 qdev_free(dev);
490 return 0;
491}
492
Michael Tokarev3b29a102011-04-06 17:51:59 +0400493
494/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200495 returning an error value. This is okay during machine creation.
496 Don't use for hotplug, because there callers need to recover from
497 failure. Exception: if you know the device's init() callback can't
498 fail, then qdev_init_nofail() can't fail either, and is therefore
499 usable even then. But relying on the device implementation that
500 way is somewhat unclean, and best avoided. */
501void qdev_init_nofail(DeviceState *dev)
502{
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600503 DeviceInfo *info = qdev_get_info(dev);
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200504
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200505 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200506 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200507 exit(1);
508 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200509}
510
Anthony Liguori44677de2011-12-12 14:29:26 -0600511static void qdev_property_del_all(DeviceState *dev)
512{
513 while (!QTAILQ_EMPTY(&dev->properties)) {
514 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
515
516 QTAILQ_REMOVE(&dev->properties, prop, node);
517
518 if (prop->release) {
519 prop->release(dev, prop->name, prop->opaque);
520 }
521
522 g_free(prop->name);
523 g_free(prop->type);
524 g_free(prop);
525 }
526}
527
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600528static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
529{
530 DeviceProperty *prop;
531
532 QTAILQ_FOREACH(prop, &dev->properties, node) {
533 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
534 break;
535 }
536 }
537
538 g_assert(prop != NULL);
539
540 QTAILQ_REMOVE(&dev->properties, prop, node);
541
542 if (prop->release) {
543 prop->release(dev, prop->name, prop->opaque);
544 }
545
546 g_free(prop->name);
547 g_free(prop->type);
548 g_free(prop);
549}
550
Paul Brook02e2da42009-05-23 00:05:19 +0100551/* Unlink device from bus and free the structure. */
552void qdev_free(DeviceState *dev)
553{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200554 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200555 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200556
Anthony Liguori44677de2011-12-12 14:29:26 -0600557 qdev_property_del_all(dev);
558
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200559 if (dev->state == DEV_STATE_INITIALIZED) {
560 while (dev->num_child_bus) {
561 bus = QLIST_FIRST(&dev->child_bus);
562 qbus_free(bus);
563 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600564 if (qdev_get_info(dev)->vmsd)
565 vmstate_unregister(dev, qdev_get_info(dev)->vmsd, dev);
566 if (qdev_get_info(dev)->exit)
567 qdev_get_info(dev)->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200568 if (dev->opts)
569 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200570 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200571 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600572 for (prop = qdev_get_info(dev)->props; prop && prop->name; prop++) {
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200573 if (prop->info->free) {
574 prop->info->free(dev, prop);
575 }
576 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600577 if (dev->parent) {
578 qdev_property_del_child(dev->parent, dev, NULL);
579 }
580 if (dev->ref != 0) {
581 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
582 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600583 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100584}
585
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200586void qdev_machine_creation_done(void)
587{
588 /*
589 * ok, initial machine setup is done, starting from now we can
590 * only create hotpluggable devices
591 */
592 qdev_hotplug = 1;
593}
594
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700595bool qdev_machine_modified(void)
596{
597 return qdev_hot_added || qdev_hot_removed;
598}
599
Paul Brookaae94602009-05-14 22:35:06 +0100600/* Get a character (serial) device interface. */
601CharDriverState *qdev_init_chardev(DeviceState *dev)
602{
603 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530604
605 /* FIXME: This function needs to go away: use chardev properties! */
606 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100607}
608
Paul Brook02e2da42009-05-23 00:05:19 +0100609BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100610{
Paul Brook02e2da42009-05-23 00:05:19 +0100611 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100612}
613
Paul Brookaae94602009-05-14 22:35:06 +0100614void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
615{
616 assert(dev->num_gpio_in == 0);
617 dev->num_gpio_in = n;
618 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
619}
620
621void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
622{
623 assert(dev->num_gpio_out == 0);
624 dev->num_gpio_out = n;
625 dev->gpio_out = pins;
626}
627
628qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
629{
630 assert(n >= 0 && n < dev->num_gpio_in);
631 return dev->gpio_in[n];
632}
633
634void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
635{
636 assert(n >= 0 && n < dev->num_gpio_out);
637 dev->gpio_out[n] = pin;
638}
639
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200640void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
641{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200642 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200643 if (nd->vlan)
644 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
645 if (nd->netdev)
646 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530647 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200648 qdev_prop_exists(dev, "vectors")) {
649 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
650 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100651 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200652}
653
Paul Brook02e2da42009-05-23 00:05:19 +0100654BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100655{
Paul Brook02e2da42009-05-23 00:05:19 +0100656 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100657
Blue Swirl72cf2d42009-09-12 07:36:22 +0000658 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100659 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100660 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100661 }
662 }
663 return NULL;
664}
665
Anthony Liguori81699d82010-11-19 18:55:58 +0900666int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
667 qbus_walkerfn *busfn, void *opaque)
668{
669 DeviceState *dev;
670 int err;
671
672 if (busfn) {
673 err = busfn(bus, opaque);
674 if (err) {
675 return err;
676 }
677 }
678
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200679 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900680 err = qdev_walk_children(dev, devfn, busfn, opaque);
681 if (err < 0) {
682 return err;
683 }
684 }
685
686 return 0;
687}
688
689int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
690 qbus_walkerfn *busfn, void *opaque)
691{
692 BusState *bus;
693 int err;
694
695 if (devfn) {
696 err = devfn(dev, opaque);
697 if (err) {
698 return err;
699 }
700 }
701
702 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
703 err = qbus_walk_children(bus, devfn, busfn, opaque);
704 if (err < 0) {
705 return err;
706 }
707 }
708
709 return 0;
710}
711
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200712static BusState *qbus_find_recursive(BusState *bus, const char *name,
713 const BusInfo *info)
714{
715 DeviceState *dev;
716 BusState *child, *ret;
717 int match = 1;
718
719 if (name && (strcmp(bus->name, name) != 0)) {
720 match = 0;
721 }
722 if (info && (bus->info != info)) {
723 match = 0;
724 }
725 if (match) {
726 return bus;
727 }
728
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200729 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000730 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200731 ret = qbus_find_recursive(child, name, info);
732 if (ret) {
733 return ret;
734 }
735 }
736 }
737 return NULL;
738}
739
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900740DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200741{
742 DeviceState *dev, *ret;
743 BusState *child;
744
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200745 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200746 if (dev->id && strcmp(dev->id, id) == 0)
747 return dev;
748 QLIST_FOREACH(child, &dev->child_bus, sibling) {
749 ret = qdev_find_recursive(child, id);
750 if (ret) {
751 return ret;
752 }
753 }
754 }
755 return NULL;
756}
757
Markus Armbruster53db16b2010-02-18 18:55:59 +0100758static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200759{
760 BusState *child;
761 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200762
Markus Armbruster53db16b2010-02-18 18:55:59 +0100763 error_printf("child busses at \"%s\":",
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600764 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
Blue Swirl72cf2d42009-09-12 07:36:22 +0000765 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100766 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200767 sep = ", ";
768 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100769 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200770}
771
Markus Armbruster53db16b2010-02-18 18:55:59 +0100772static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200773{
774 DeviceState *dev;
775 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200776
Markus Armbruster53db16b2010-02-18 18:55:59 +0100777 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200778 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600779 error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200780 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100781 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200782 sep = ", ";
783 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100784 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200785}
786
787static BusState *qbus_find_bus(DeviceState *dev, char *elem)
788{
789 BusState *child;
790
Blue Swirl72cf2d42009-09-12 07:36:22 +0000791 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200792 if (strcmp(child->name, elem) == 0) {
793 return child;
794 }
795 }
796 return NULL;
797}
798
799static DeviceState *qbus_find_dev(BusState *bus, char *elem)
800{
801 DeviceState *dev;
802
803 /*
804 * try to match in order:
805 * (1) instance id, if present
806 * (2) driver name
807 * (3) driver alias, if present
808 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200809 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200810 if (dev->id && strcmp(dev->id, elem) == 0) {
811 return dev;
812 }
813 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200814 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600815 if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200816 return dev;
817 }
818 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200819 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori30fbb9f2011-12-04 11:08:36 -0600820 if (qdev_get_info(dev)->alias && strcmp(qdev_get_info(dev)->alias, elem) == 0) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200821 return dev;
822 }
823 }
824 return NULL;
825}
826
827static BusState *qbus_find(const char *path)
828{
829 DeviceState *dev;
830 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100831 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200832 int pos, len;
833
834 /* find start element */
835 if (path[0] == '/') {
836 bus = main_system_bus;
837 pos = 0;
838 } else {
839 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100840 assert(!path[0]);
841 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200842 }
843 bus = qbus_find_recursive(main_system_bus, elem, NULL);
844 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100845 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200846 return NULL;
847 }
848 pos = len;
849 }
850
851 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100852 assert(path[pos] == '/' || !path[pos]);
853 while (path[pos] == '/') {
854 pos++;
855 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200856 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200857 return bus;
858 }
859
860 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100861 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
862 assert(0);
863 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200864 }
865 pos += len;
866 dev = qbus_find_dev(bus, elem);
867 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100868 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100869 if (!monitor_cur_is_qmp()) {
870 qbus_list_dev(bus);
871 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200872 return NULL;
873 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100874
875 assert(path[pos] == '/' || !path[pos]);
876 while (path[pos] == '/') {
877 pos++;
878 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200879 if (path[pos] == '\0') {
880 /* last specified element is a device. If it has exactly
881 * one child bus accept it nevertheless */
882 switch (dev->num_child_bus) {
883 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100884 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200885 return NULL;
886 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000887 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200888 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100889 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100890 if (!monitor_cur_is_qmp()) {
891 qbus_list_bus(dev);
892 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200893 return NULL;
894 }
895 }
896
897 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100898 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
899 assert(0);
900 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200901 }
902 pos += len;
903 bus = qbus_find_bus(dev, elem);
904 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100905 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100906 if (!monitor_cur_is_qmp()) {
907 qbus_list_bus(dev);
908 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200909 return NULL;
910 }
911 }
912}
913
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200914void qbus_create_inplace(BusState *bus, BusInfo *info,
915 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100916{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200917 char *buf;
918 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100919
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200920 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100921 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200922
923 if (name) {
924 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500925 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200926 } else if (parent && parent->id) {
927 /* parent device has id -> use it for bus name */
928 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500929 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200930 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
931 bus->name = buf;
932 } else {
933 /* no id -> use lowercase bus type for bus name */
934 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500935 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200936 len = snprintf(buf, len, "%s.%d", info->name,
937 parent ? parent->num_child_bus : 0);
938 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200939 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200940 bus->name = buf;
941 }
942
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200943 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100944 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000945 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200946 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900947 } else if (bus != main_system_bus) {
948 /* TODO: once all bus devices are qdevified,
949 only reset handler for main_system_bus should be registered here. */
950 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100951 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200952}
953
954BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
955{
956 BusState *bus;
957
Anthony Liguori7267c092011-08-20 22:09:37 -0500958 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200959 bus->qdev_allocated = 1;
960 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100961 return bus;
962}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100963
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900964static void main_system_bus_create(void)
965{
966 /* assign main_system_bus before qbus_create_inplace()
967 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500968 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900969 main_system_bus->qdev_allocated = 1;
970 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
971 "main-system-bus");
972}
973
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200974void qbus_free(BusState *bus)
975{
976 DeviceState *dev;
977
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200978 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200979 qdev_free(dev);
980 }
981 if (bus->parent) {
982 QLIST_REMOVE(bus, sibling);
983 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900984 } else {
985 assert(bus != main_system_bus); /* main_system_bus is never freed */
986 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200987 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500988 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200989 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500990 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200991 }
992}
993
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100994#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
995static void qbus_print(Monitor *mon, BusState *bus, int indent);
996
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200997static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
998 const char *prefix, int indent)
999{
1000 char buf[64];
1001
1002 if (!props)
1003 return;
1004 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +01001005 /*
1006 * TODO Properties without a print method are just for dirty
1007 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
1008 * marked for removal. The test props->info->print should be
1009 * removed along with it.
1010 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001011 if (props->info->print) {
1012 props->info->print(dev, props, buf, sizeof(buf));
1013 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
1014 }
1015 props++;
1016 }
1017}
1018
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001019static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
1020{
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001021 BusState *child;
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001022 qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
Gerd Hoffmannccb63de2009-07-15 13:43:34 +02001023 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001024 indent += 2;
1025 if (dev->num_gpio_in) {
1026 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
1027 }
1028 if (dev->num_gpio_out) {
1029 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
1030 }
Anthony Liguori30fbb9f2011-12-04 11:08:36 -06001031 qdev_print_props(mon, dev, qdev_get_info(dev)->props, "dev", indent);
Gerd Hoffmannee6847d2009-07-15 13:43:31 +02001032 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001033 if (dev->parent_bus->info->print_dev)
1034 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +00001035 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001036 qbus_print(mon, child, indent);
1037 }
1038}
1039
1040static void qbus_print(Monitor *mon, BusState *bus, int indent)
1041{
1042 struct DeviceState *dev;
1043
1044 qdev_printf("bus: %s\n", bus->name);
1045 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +02001046 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +02001047 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +01001048 qdev_print(mon, dev, indent);
1049 }
1050}
1051#undef qdev_printf
1052
1053void do_info_qtree(Monitor *mon)
1054{
1055 if (main_system_bus)
1056 qbus_print(mon, main_system_bus, 0);
1057}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001058
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001059void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001060{
1061 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001062
1063 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +01001064 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001065 }
1066}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001067
Markus Armbruster8bc27242010-02-10 20:52:01 +01001068int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001069{
1070 QemuOpts *opts;
1071
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001072 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001073 if (!opts) {
1074 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001075 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001076 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1077 qemu_opts_del(opts);
1078 return 0;
1079 }
1080 if (!qdev_device_add(opts)) {
1081 qemu_opts_del(opts);
1082 return -1;
1083 }
1084 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001085}
1086
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001087int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001088{
1089 const char *id = qdict_get_str(qdict, "id");
1090 DeviceState *dev;
1091
1092 dev = qdev_find_recursive(main_system_bus, id);
1093 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001094 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1095 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001096 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001097 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001098}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001099
1100static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1101{
1102 int l = 0;
1103
1104 if (dev && dev->parent_bus) {
1105 char *d;
1106 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1107 if (dev->parent_bus->info->get_fw_dev_path) {
1108 d = dev->parent_bus->info->get_fw_dev_path(dev);
1109 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001110 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001111 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001112 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001113 }
1114 }
1115 l += snprintf(p + l , size - l, "/");
1116
1117 return l;
1118}
1119
1120char* qdev_get_fw_dev_path(DeviceState *dev)
1121{
1122 char path[128];
1123 int l;
1124
1125 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1126
1127 path[l-1] = '\0';
1128
1129 return strdup(path);
1130}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001131
Anthony Liguoricd34d662011-12-12 14:29:43 -06001132char *qdev_get_type(DeviceState *dev, Error **errp)
1133{
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001134 return g_strdup(object_get_typename(OBJECT(dev)));
Anthony Liguoricd34d662011-12-12 14:29:43 -06001135}
1136
Anthony Liguori85ed3032011-12-12 14:29:25 -06001137void qdev_ref(DeviceState *dev)
1138{
1139 dev->ref++;
1140}
1141
1142void qdev_unref(DeviceState *dev)
1143{
1144 g_assert(dev->ref > 0);
1145 dev->ref--;
1146}
Anthony Liguori44677de2011-12-12 14:29:26 -06001147
1148void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1149 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1150 DevicePropertyRelease *release,
1151 void *opaque, Error **errp)
1152{
1153 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1154
1155 prop->name = g_strdup(name);
1156 prop->type = g_strdup(type);
1157
1158 prop->get = get;
1159 prop->set = set;
1160 prop->release = release;
1161 prop->opaque = opaque;
1162
1163 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1164}
1165
1166static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1167{
1168 DeviceProperty *prop;
1169
1170 QTAILQ_FOREACH(prop, &dev->properties, node) {
1171 if (strcmp(prop->name, name) == 0) {
1172 return prop;
1173 }
1174 }
1175
1176 return NULL;
1177}
1178
1179void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1180 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;
1187 }
1188
1189 if (!prop->get) {
1190 error_set(errp, QERR_PERMISSION_DENIED);
1191 } else {
1192 prop->get(dev, v, prop->opaque, name, errp);
1193 }
1194}
1195
1196void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1197 Error **errp)
1198{
1199 DeviceProperty *prop = qdev_property_find(dev, name);
1200
1201 if (prop == NULL) {
1202 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1203 return;
1204 }
1205
1206 if (!prop->set) {
1207 error_set(errp, QERR_PERMISSION_DENIED);
1208 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001209 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001210 }
1211}
1212
1213const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1214{
1215 DeviceProperty *prop = qdev_property_find(dev, name);
1216
1217 if (prop == NULL) {
1218 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1219 return NULL;
1220 }
1221
1222 return prop->type;
1223}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001224
1225/**
1226 * Legacy property handling
1227 */
1228
1229static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1230 const char *name, Error **errp)
1231{
1232 Property *prop = opaque;
1233
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001234 char buffer[1024];
1235 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001236
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001237 prop->info->print(dev, prop, buffer, sizeof(buffer));
1238 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001239}
1240
1241static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1242 const char *name, Error **errp)
1243{
1244 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001245 Error *local_err = NULL;
1246 char *ptr = NULL;
1247 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001248
1249 if (dev->state != DEV_STATE_CREATED) {
1250 error_set(errp, QERR_PERMISSION_DENIED);
1251 return;
1252 }
1253
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001254 visit_type_str(v, &ptr, name, &local_err);
1255 if (local_err) {
1256 error_propagate(errp, local_err);
1257 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001258 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001259
1260 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001261 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001262 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001263}
1264
1265/**
1266 * @qdev_add_legacy_property - adds a legacy property
1267 *
1268 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001269 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001270 *
1271 * Legacy properties are always processed as strings. The format of the string
1272 * depends on the property type.
1273 */
1274void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1275 Error **errp)
1276{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001277 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001278
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001279 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001280 type = g_strdup_printf("legacy<%s>",
1281 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001282
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001283 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001284 prop->info->print ? qdev_get_legacy_property : NULL,
1285 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001286 NULL,
1287 prop, errp);
1288
1289 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001290 g_free(name);
1291}
1292
1293/**
1294 * @qdev_property_add_static - add a @Property to a device.
1295 *
1296 * Static properties access data in a struct. The actual type of the
1297 * property and the field depends on the property type.
1298 */
1299void qdev_property_add_static(DeviceState *dev, Property *prop,
1300 Error **errp)
1301{
1302 qdev_property_add(dev, prop->name, prop->info->name,
1303 prop->info->get, prop->info->set,
1304 NULL,
1305 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001306}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001307
1308DeviceState *qdev_get_root(void)
1309{
1310 static DeviceState *qdev_root;
1311
1312 if (!qdev_root) {
1313 qdev_root = qdev_create(NULL, "container");
1314 qdev_init_nofail(qdev_root);
1315 }
1316
1317 return qdev_root;
1318}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001319
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001320static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1321 const char *name, Error **errp)
1322{
1323 DeviceState *child = opaque;
1324 gchar *path;
1325
1326 path = qdev_get_canonical_path(child);
1327 visit_type_str(v, &path, name, errp);
1328 g_free(path);
1329}
1330
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001331static void qdev_release_child_property(DeviceState *dev, const char *name,
1332 void *opaque)
1333{
1334 DeviceState *child = opaque;
1335
1336 qdev_unref(child);
1337}
1338
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001339void qdev_property_add_child(DeviceState *dev, const char *name,
1340 DeviceState *child, Error **errp)
1341{
1342 gchar *type;
1343
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001344 type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001345
1346 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001347 NULL, qdev_release_child_property,
1348 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001349
1350 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001351 g_assert(child->parent == NULL);
1352 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001353
1354 g_free(type);
1355}
1356
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001357static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1358 const char *name, Error **errp)
1359{
1360 DeviceState **child = opaque;
1361 gchar *path;
1362
1363 if (*child) {
1364 path = qdev_get_canonical_path(*child);
1365 visit_type_str(v, &path, name, errp);
1366 g_free(path);
1367 } else {
1368 path = (gchar *)"";
1369 visit_type_str(v, &path, name, errp);
1370 }
1371}
1372
1373static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1374 const char *name, Error **errp)
1375{
1376 DeviceState **child = opaque;
1377 bool ambiguous = false;
1378 const char *type;
1379 char *path;
1380
1381 type = qdev_property_get_type(dev, name, NULL);
1382
1383 visit_type_str(v, &path, name, errp);
1384
1385 if (*child) {
1386 qdev_unref(*child);
1387 }
1388
1389 if (strcmp(path, "") != 0) {
1390 DeviceState *target;
1391
1392 target = qdev_resolve_path(path, &ambiguous);
1393 if (target) {
1394 gchar *target_type;
1395
Anthony Liguorif79f2bf2011-12-04 11:17:51 -06001396 target_type = g_strdup_printf("link<%s>", object_get_typename(OBJECT(target)));
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001397 if (strcmp(target_type, type) == 0) {
1398 *child = target;
1399 qdev_ref(target);
1400 } else {
1401 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1402 }
1403
1404 g_free(target_type);
1405 } else {
1406 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1407 }
1408 } else {
1409 *child = NULL;
1410 }
1411
1412 g_free(path);
1413}
1414
1415void qdev_property_add_link(DeviceState *dev, const char *name,
1416 const char *type, DeviceState **child,
1417 Error **errp)
1418{
1419 gchar *full_type;
1420
1421 full_type = g_strdup_printf("link<%s>", type);
1422
1423 qdev_property_add(dev, name, full_type,
1424 qdev_get_link_property,
1425 qdev_set_link_property,
1426 NULL, child, errp);
1427
1428 g_free(full_type);
1429}
1430
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001431gchar *qdev_get_canonical_path(DeviceState *dev)
1432{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001433 DeviceState *root = qdev_get_root();
1434 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001435
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001436 while (dev != root) {
1437 DeviceProperty *prop = NULL;
1438
1439 g_assert(dev->parent != NULL);
1440
1441 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1442 if (!strstart(prop->type, "child<", NULL)) {
1443 continue;
1444 }
1445
1446 if (prop->opaque == dev) {
1447 if (path) {
1448 newpath = g_strdup_printf("%s/%s", prop->name, path);
1449 g_free(path);
1450 path = newpath;
1451 } else {
1452 path = g_strdup(prop->name);
1453 }
1454 break;
1455 }
1456 }
1457
1458 g_assert(prop != NULL);
1459
1460 dev = dev->parent;
1461 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001462
1463 newpath = g_strdup_printf("/%s", path);
1464 g_free(path);
1465
1466 return newpath;
1467}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001468
1469static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1470 gchar **parts,
1471 int index)
1472{
1473 DeviceProperty *prop;
1474 DeviceState *child;
1475
1476 if (parts[index] == NULL) {
1477 return parent;
1478 }
1479
1480 if (strcmp(parts[index], "") == 0) {
1481 return qdev_resolve_abs_path(parent, parts, index + 1);
1482 }
1483
1484 prop = qdev_property_find(parent, parts[index]);
1485 if (prop == NULL) {
1486 return NULL;
1487 }
1488
1489 child = NULL;
1490 if (strstart(prop->type, "link<", NULL)) {
1491 DeviceState **pchild = prop->opaque;
1492 if (*pchild) {
1493 child = *pchild;
1494 }
1495 } else if (strstart(prop->type, "child<", NULL)) {
1496 child = prop->opaque;
1497 }
1498
1499 if (!child) {
1500 return NULL;
1501 }
1502
1503 return qdev_resolve_abs_path(child, parts, index + 1);
1504}
1505
1506static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1507 gchar **parts,
1508 bool *ambiguous)
1509{
1510 DeviceState *dev;
1511 DeviceProperty *prop;
1512
1513 dev = qdev_resolve_abs_path(parent, parts, 0);
1514
1515 QTAILQ_FOREACH(prop, &parent->properties, node) {
1516 DeviceState *found;
1517
1518 if (!strstart(prop->type, "child<", NULL)) {
1519 continue;
1520 }
1521
1522 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1523 if (found) {
1524 if (dev) {
1525 if (ambiguous) {
1526 *ambiguous = true;
1527 }
1528 return NULL;
1529 }
1530 dev = found;
1531 }
1532
1533 if (ambiguous && *ambiguous) {
1534 return NULL;
1535 }
1536 }
1537
1538 return dev;
1539}
1540
1541DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1542{
1543 bool partial_path = true;
1544 DeviceState *dev;
1545 gchar **parts;
1546
1547 parts = g_strsplit(path, "/", 0);
1548 if (parts == NULL || parts[0] == NULL) {
1549 g_strfreev(parts);
1550 return qdev_get_root();
1551 }
1552
1553 if (strcmp(parts[0], "") == 0) {
1554 partial_path = false;
1555 }
1556
1557 if (partial_path) {
1558 if (ambiguous) {
1559 *ambiguous = false;
1560 }
1561 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1562 } else {
1563 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1564 }
1565
1566 g_strfreev(parts);
1567
1568 return dev;
1569}
1570
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001571typedef struct StringProperty
1572{
1573 char *(*get)(DeviceState *, Error **);
1574 void (*set)(DeviceState *, const char *, Error **);
1575} StringProperty;
1576
1577static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1578 const char *name, Error **errp)
1579{
1580 StringProperty *prop = opaque;
1581 char *value;
1582
1583 value = prop->get(dev, errp);
1584 if (value) {
1585 visit_type_str(v, &value, name, errp);
1586 g_free(value);
1587 }
1588}
1589
1590static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1591 const char *name, Error **errp)
1592{
1593 StringProperty *prop = opaque;
1594 char *value;
1595 Error *local_err = NULL;
1596
1597 visit_type_str(v, &value, name, &local_err);
1598 if (local_err) {
1599 error_propagate(errp, local_err);
1600 return;
1601 }
1602
1603 prop->set(dev, value, errp);
1604 g_free(value);
1605}
1606
1607static void qdev_property_release_str(DeviceState *dev, const char *name,
1608 void *opaque)
1609{
1610 StringProperty *prop = opaque;
1611 g_free(prop);
1612}
1613
1614void qdev_property_add_str(DeviceState *dev, const char *name,
1615 char *(*get)(DeviceState *, Error **),
1616 void (*set)(DeviceState *, const char *, Error **),
1617 Error **errp)
1618{
1619 StringProperty *prop = g_malloc0(sizeof(*prop));
1620
1621 prop->get = get;
1622 prop->set = set;
1623
1624 qdev_property_add(dev, name, "string",
1625 get ? qdev_property_get_str : NULL,
1626 set ? qdev_property_set_str : NULL,
1627 qdev_property_release_str,
1628 prop, errp);
1629}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001630
1631void qdev_machine_init(void)
1632{
1633 qdev_get_peripheral_anon();
1634 qdev_get_peripheral();
1635}
Anthony Liguori32fea402011-12-16 14:34:46 -06001636
Anthony Liguori94afdad2011-12-04 11:36:01 -06001637void device_reset(DeviceState *dev)
1638{
1639 DeviceClass *klass = DEVICE_GET_CLASS(dev);
1640
1641 if (klass->reset) {
1642 klass->reset(dev);
1643 }
1644}
1645
Anthony Liguori32fea402011-12-16 14:34:46 -06001646static TypeInfo device_type_info = {
1647 .name = TYPE_DEVICE,
1648 .parent = TYPE_OBJECT,
1649 .instance_size = sizeof(DeviceState),
1650 .abstract = true,
1651 .class_size = sizeof(DeviceClass),
1652};
1653
1654static void init_qdev(void)
1655{
1656 type_register_static(&device_type_info);
1657}
1658
1659device_init(init_qdev);