blob: 3bc91668145bcc4f758cec36413564cc17ee59fb [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. */
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020048void qdev_register(DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010049{
Anthony Liguori32fea402011-12-16 14:34:46 -060050 TypeInfo type_info = {};
51
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020052 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020053 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010054
Anthony Liguori32fea402011-12-16 14:34:46 -060055 type_info.name = info->name;
56 type_info.parent = TYPE_DEVICE;
57 type_info.instance_size = info->size;
58
59 type_register_static(&type_info);
60
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020061 info->next = device_info_list;
62 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010063}
64
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020065static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
66{
67 DeviceInfo *info;
68
Gerd Hoffmann3320e562009-07-15 13:43:33 +020069 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020070 for (info = device_info_list; info != NULL; info = info->next) {
71 if (bus_info && info->bus_info != bus_info)
72 continue;
73 if (strcmp(info->name, name) != 0)
74 continue;
75 return info;
76 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +020077
78 /* failing that check the aliases */
79 for (info = device_info_list; info != NULL; info = info->next) {
80 if (bus_info && info->bus_info != bus_info)
81 continue;
82 if (!info->alias)
83 continue;
84 if (strcmp(info->alias, name) != 0)
85 continue;
86 return info;
87 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020088 return NULL;
89}
90
Blue Swirla369da52011-09-27 19:15:42 +000091bool qdev_exists(const char *name)
92{
93 return !!qdev_find_info(NULL, name);
94}
Paolo Bonzinica2cc782011-12-18 17:05:11 +010095static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
96 Error **errp);
97
Markus Armbruster0c175422010-02-19 19:12:18 +010098static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010099{
Paul Brookaae94602009-05-14 22:35:06 +0100100 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600101 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +0100102
Markus Armbruster0c175422010-02-19 19:12:18 +0100103 assert(bus->info == info->bus_info);
Anthony Liguori32fea402011-12-16 14:34:46 -0600104 dev = DEVICE(object_new(info->name));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +0200105 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100106 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200107 qdev_prop_set_defaults(dev, dev->info->props);
108 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +0100109 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200110 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200111 if (qdev_hotplug) {
112 assert(bus->allow_hotplug);
113 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700114 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200115 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200116 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600117 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200118 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600119
120 for (prop = dev->info->props; prop && prop->name; prop++) {
121 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100122 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600123 }
124
125 for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
126 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100127 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600128 }
129
Anthony Liguoricd34d662011-12-12 14:29:43 -0600130 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
131
Paul Brookaae94602009-05-14 22:35:06 +0100132 return dev;
133}
134
Markus Armbruster0c175422010-02-19 19:12:18 +0100135/* Create a new device. This only initializes the device state structure
136 and allows properties to be set. qdev_init should be called to
137 initialize the actual device emulation. */
138DeviceState *qdev_create(BusState *bus, const char *name)
139{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000140 DeviceState *dev;
141
142 dev = qdev_try_create(bus, name);
143 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100144 if (bus) {
145 hw_error("Unknown device '%s' for bus '%s'\n", name,
146 bus->info->name);
147 } else {
148 hw_error("Unknown device '%s' for default sysbus\n", name);
149 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000150 }
151
152 return dev;
153}
154
155DeviceState *qdev_try_create(BusState *bus, const char *name)
156{
Markus Armbruster0c175422010-02-19 19:12:18 +0100157 DeviceInfo *info;
158
159 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100160 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100161 }
162
163 info = qdev_find_info(bus->info, name);
164 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000165 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100166 }
167
168 return qdev_create_from_info(bus, info);
169}
170
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100171static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200172{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100173 error_printf("name \"%s\", bus %s",
174 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200175 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100176 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200177 }
178 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100179 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200180 }
181 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100182 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200183 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100184 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200185}
186
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200187static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200188{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200189 DeviceState *dev = opaque;
190
191 if (strcmp(name, "driver") == 0)
192 return 0;
193 if (strcmp(name, "bus") == 0)
194 return 0;
195
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100196 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200197 return -1;
198 }
199 return 0;
200}
201
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100202int qdev_device_help(QemuOpts *opts)
203{
204 const char *driver;
205 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100206 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100207
208 driver = qemu_opt_get(opts, "driver");
209 if (driver && !strcmp(driver, "?")) {
210 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100211 if (info->no_user) {
212 continue; /* not available, don't show */
213 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100214 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100215 }
216 return 1;
217 }
218
Markus Armbruster542379f2011-11-08 11:00:38 +0100219 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100220 return 0;
221 }
222
223 info = qdev_find_info(NULL, driver);
224 if (!info) {
225 return 0;
226 }
227
228 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100229 /*
230 * TODO Properties without a parser are just for dirty hacks.
231 * qdev_prop_ptr is the only such PropertyInfo. It's marked
232 * for removal. This conditional should be removed along with
233 * it.
234 */
235 if (!prop->info->parse) {
236 continue; /* no way to set it, don't show */
237 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100238 error_printf("%s.%s=%s\n", info->name, prop->name,
239 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100240 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200241 for (prop = info->bus_info->props; prop && prop->name; prop++) {
242 if (!prop->info->parse) {
243 continue; /* no way to set it, don't show */
244 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100245 error_printf("%s.%s=%s\n", info->name, prop->name,
246 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200247 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100248 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100249}
250
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600251static DeviceState *qdev_get_peripheral(void)
252{
253 static DeviceState *dev;
254
255 if (dev == NULL) {
256 dev = qdev_create(NULL, "container");
257 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
258 qdev_init_nofail(dev);
259 }
260
261 return dev;
262}
263
Anthony Liguori8eb02832011-12-12 14:29:37 -0600264static DeviceState *qdev_get_peripheral_anon(void)
265{
266 static DeviceState *dev;
267
268 if (dev == NULL) {
269 dev = qdev_create(NULL, "container");
270 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
271 qdev_init_nofail(dev);
272 }
273
274 return dev;
275}
276
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200277DeviceState *qdev_device_add(QemuOpts *opts)
278{
279 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200280 DeviceInfo *info;
281 DeviceState *qdev;
282 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200283
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200284 driver = qemu_opt_get(opts, "driver");
285 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100286 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200287 return NULL;
288 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200289
290 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200291 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100292 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100293 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100294 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200295 return NULL;
296 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200297
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200298 /* find bus */
299 path = qemu_opt_get(opts, "bus");
300 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200301 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100302 if (!bus) {
303 return NULL;
304 }
305 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100306 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
307 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100308 return NULL;
309 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200310 } else {
311 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100312 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100313 qerror_report(QERR_NO_BUS_FOR_DEVICE,
314 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100315 return NULL;
316 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200317 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200318 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100319 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200320 return NULL;
321 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200322
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200323 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100324 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200325 id = qemu_opts_id(opts);
326 if (id) {
327 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600328 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600329 } else {
330 static int anon_count;
331 gchar *name = g_strdup_printf("device[%d]", anon_count++);
332 qdev_property_add_child(qdev_get_peripheral_anon(), name,
333 qdev, NULL);
334 g_free(name);
335 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200336 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
337 qdev_free(qdev);
338 return NULL;
339 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200340 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100341 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200342 return NULL;
343 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200344 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200345 return qdev;
346}
347
Paul Brookaae94602009-05-14 22:35:06 +0100348/* Initialize a device. Device properties should be set before calling
349 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200350 calling this function.
351 On failure, destroy the device and return negative value.
352 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200353int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100354{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200355 int rc;
356
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200357 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200358 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200359 if (rc < 0) {
360 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200361 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200362 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200363 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600364 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200365 dev->instance_id_alias,
366 dev->alias_required_for_version);
367 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200368 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200369 if (dev->hotplugged && dev->info->reset) {
370 dev->info->reset(dev);
371 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200372 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100373}
374
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200375void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
376 int required_for_version)
377{
378 assert(dev->state == DEV_STATE_CREATED);
379 dev->instance_id_alias = alias_id;
380 dev->alias_required_for_version = required_for_version;
381}
382
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200383int qdev_unplug(DeviceState *dev)
384{
385 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100386 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200387 return -1;
388 }
Amit Shah593831d2009-11-02 14:56:41 +0530389 assert(dev->info->unplug != NULL);
390
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700391 qdev_hot_removed = true;
392
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200393 return dev->info->unplug(dev);
394}
395
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900396static int qdev_reset_one(DeviceState *dev, void *opaque)
397{
398 if (dev->info->reset) {
399 dev->info->reset(dev);
400 }
401
402 return 0;
403}
404
405BusState *sysbus_get_default(void)
406{
Stefan Weil68694892010-12-16 19:33:22 +0100407 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900408 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100409 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900410 return main_system_bus;
411}
412
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900413static int qbus_reset_one(BusState *bus, void *opaque)
414{
415 if (bus->info->reset) {
416 return bus->info->reset(bus);
417 }
418 return 0;
419}
420
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900421void qdev_reset_all(DeviceState *dev)
422{
423 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
424}
425
Isaku Yamahata80376c32010-12-20 14:33:35 +0900426void qbus_reset_all_fn(void *opaque)
427{
428 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200429 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900430}
431
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200432/* can be used as ->unplug() callback for the simple cases */
433int qdev_simple_unplug_cb(DeviceState *dev)
434{
435 /* just zap it */
436 qdev_free(dev);
437 return 0;
438}
439
Michael Tokarev3b29a102011-04-06 17:51:59 +0400440
441/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200442 returning an error value. This is okay during machine creation.
443 Don't use for hotplug, because there callers need to recover from
444 failure. Exception: if you know the device's init() callback can't
445 fail, then qdev_init_nofail() can't fail either, and is therefore
446 usable even then. But relying on the device implementation that
447 way is somewhat unclean, and best avoided. */
448void qdev_init_nofail(DeviceState *dev)
449{
450 DeviceInfo *info = dev->info;
451
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200452 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200453 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200454 exit(1);
455 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200456}
457
Anthony Liguori44677de2011-12-12 14:29:26 -0600458static void qdev_property_del_all(DeviceState *dev)
459{
460 while (!QTAILQ_EMPTY(&dev->properties)) {
461 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
462
463 QTAILQ_REMOVE(&dev->properties, prop, node);
464
465 if (prop->release) {
466 prop->release(dev, prop->name, prop->opaque);
467 }
468
469 g_free(prop->name);
470 g_free(prop->type);
471 g_free(prop);
472 }
473}
474
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600475static void qdev_property_del_child(DeviceState *dev, DeviceState *child, Error **errp)
476{
477 DeviceProperty *prop;
478
479 QTAILQ_FOREACH(prop, &dev->properties, node) {
480 if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
481 break;
482 }
483 }
484
485 g_assert(prop != NULL);
486
487 QTAILQ_REMOVE(&dev->properties, prop, node);
488
489 if (prop->release) {
490 prop->release(dev, prop->name, prop->opaque);
491 }
492
493 g_free(prop->name);
494 g_free(prop->type);
495 g_free(prop);
496}
497
Paul Brook02e2da42009-05-23 00:05:19 +0100498/* Unlink device from bus and free the structure. */
499void qdev_free(DeviceState *dev)
500{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200501 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200502 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200503
Anthony Liguori44677de2011-12-12 14:29:26 -0600504 qdev_property_del_all(dev);
505
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200506 if (dev->state == DEV_STATE_INITIALIZED) {
507 while (dev->num_child_bus) {
508 bus = QLIST_FIRST(&dev->child_bus);
509 qbus_free(bus);
510 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200511 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600512 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200513 if (dev->info->exit)
514 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200515 if (dev->opts)
516 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200517 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200518 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200519 for (prop = dev->info->props; prop && prop->name; prop++) {
520 if (prop->info->free) {
521 prop->info->free(dev, prop);
522 }
523 }
Anthony Liguori024a6fb2012-01-13 07:45:55 -0600524 if (dev->parent) {
525 qdev_property_del_child(dev->parent, dev, NULL);
526 }
527 if (dev->ref != 0) {
528 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
529 }
Anthony Liguori32fea402011-12-16 14:34:46 -0600530 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100531}
532
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200533void qdev_machine_creation_done(void)
534{
535 /*
536 * ok, initial machine setup is done, starting from now we can
537 * only create hotpluggable devices
538 */
539 qdev_hotplug = 1;
540}
541
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700542bool qdev_machine_modified(void)
543{
544 return qdev_hot_added || qdev_hot_removed;
545}
546
Paul Brookaae94602009-05-14 22:35:06 +0100547/* Get a character (serial) device interface. */
548CharDriverState *qdev_init_chardev(DeviceState *dev)
549{
550 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530551
552 /* FIXME: This function needs to go away: use chardev properties! */
553 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100554}
555
Paul Brook02e2da42009-05-23 00:05:19 +0100556BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100557{
Paul Brook02e2da42009-05-23 00:05:19 +0100558 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100559}
560
Paul Brookaae94602009-05-14 22:35:06 +0100561void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
562{
563 assert(dev->num_gpio_in == 0);
564 dev->num_gpio_in = n;
565 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
566}
567
568void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
569{
570 assert(dev->num_gpio_out == 0);
571 dev->num_gpio_out = n;
572 dev->gpio_out = pins;
573}
574
575qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
576{
577 assert(n >= 0 && n < dev->num_gpio_in);
578 return dev->gpio_in[n];
579}
580
581void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
582{
583 assert(n >= 0 && n < dev->num_gpio_out);
584 dev->gpio_out[n] = pin;
585}
586
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200587void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
588{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200589 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200590 if (nd->vlan)
591 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
592 if (nd->netdev)
593 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530594 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200595 qdev_prop_exists(dev, "vectors")) {
596 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
597 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100598 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200599}
600
Paul Brook02e2da42009-05-23 00:05:19 +0100601BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100602{
Paul Brook02e2da42009-05-23 00:05:19 +0100603 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100604
Blue Swirl72cf2d42009-09-12 07:36:22 +0000605 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100606 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100607 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100608 }
609 }
610 return NULL;
611}
612
Anthony Liguori81699d82010-11-19 18:55:58 +0900613int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
614 qbus_walkerfn *busfn, void *opaque)
615{
616 DeviceState *dev;
617 int err;
618
619 if (busfn) {
620 err = busfn(bus, opaque);
621 if (err) {
622 return err;
623 }
624 }
625
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200626 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900627 err = qdev_walk_children(dev, devfn, busfn, opaque);
628 if (err < 0) {
629 return err;
630 }
631 }
632
633 return 0;
634}
635
636int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
637 qbus_walkerfn *busfn, void *opaque)
638{
639 BusState *bus;
640 int err;
641
642 if (devfn) {
643 err = devfn(dev, opaque);
644 if (err) {
645 return err;
646 }
647 }
648
649 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
650 err = qbus_walk_children(bus, devfn, busfn, opaque);
651 if (err < 0) {
652 return err;
653 }
654 }
655
656 return 0;
657}
658
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200659static BusState *qbus_find_recursive(BusState *bus, const char *name,
660 const BusInfo *info)
661{
662 DeviceState *dev;
663 BusState *child, *ret;
664 int match = 1;
665
666 if (name && (strcmp(bus->name, name) != 0)) {
667 match = 0;
668 }
669 if (info && (bus->info != info)) {
670 match = 0;
671 }
672 if (match) {
673 return bus;
674 }
675
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200676 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000677 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200678 ret = qbus_find_recursive(child, name, info);
679 if (ret) {
680 return ret;
681 }
682 }
683 }
684 return NULL;
685}
686
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900687DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200688{
689 DeviceState *dev, *ret;
690 BusState *child;
691
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200692 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200693 if (dev->id && strcmp(dev->id, id) == 0)
694 return dev;
695 QLIST_FOREACH(child, &dev->child_bus, sibling) {
696 ret = qdev_find_recursive(child, id);
697 if (ret) {
698 return ret;
699 }
700 }
701 }
702 return NULL;
703}
704
Markus Armbruster53db16b2010-02-18 18:55:59 +0100705static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200706{
707 BusState *child;
708 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200709
Markus Armbruster53db16b2010-02-18 18:55:59 +0100710 error_printf("child busses at \"%s\":",
711 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000712 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100713 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200714 sep = ", ";
715 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100716 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200717}
718
Markus Armbruster53db16b2010-02-18 18:55:59 +0100719static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200720{
721 DeviceState *dev;
722 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200723
Markus Armbruster53db16b2010-02-18 18:55:59 +0100724 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200725 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100726 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200727 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100728 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200729 sep = ", ";
730 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100731 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200732}
733
734static BusState *qbus_find_bus(DeviceState *dev, char *elem)
735{
736 BusState *child;
737
Blue Swirl72cf2d42009-09-12 07:36:22 +0000738 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200739 if (strcmp(child->name, elem) == 0) {
740 return child;
741 }
742 }
743 return NULL;
744}
745
746static DeviceState *qbus_find_dev(BusState *bus, char *elem)
747{
748 DeviceState *dev;
749
750 /*
751 * try to match in order:
752 * (1) instance id, if present
753 * (2) driver name
754 * (3) driver alias, if present
755 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200756 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200757 if (dev->id && strcmp(dev->id, elem) == 0) {
758 return dev;
759 }
760 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200761 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200762 if (strcmp(dev->info->name, elem) == 0) {
763 return dev;
764 }
765 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200766 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200767 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
768 return dev;
769 }
770 }
771 return NULL;
772}
773
774static BusState *qbus_find(const char *path)
775{
776 DeviceState *dev;
777 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100778 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200779 int pos, len;
780
781 /* find start element */
782 if (path[0] == '/') {
783 bus = main_system_bus;
784 pos = 0;
785 } else {
786 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100787 assert(!path[0]);
788 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200789 }
790 bus = qbus_find_recursive(main_system_bus, elem, NULL);
791 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100792 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200793 return NULL;
794 }
795 pos = len;
796 }
797
798 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100799 assert(path[pos] == '/' || !path[pos]);
800 while (path[pos] == '/') {
801 pos++;
802 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200803 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200804 return bus;
805 }
806
807 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100808 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
809 assert(0);
810 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200811 }
812 pos += len;
813 dev = qbus_find_dev(bus, elem);
814 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100815 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100816 if (!monitor_cur_is_qmp()) {
817 qbus_list_dev(bus);
818 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200819 return NULL;
820 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100821
822 assert(path[pos] == '/' || !path[pos]);
823 while (path[pos] == '/') {
824 pos++;
825 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200826 if (path[pos] == '\0') {
827 /* last specified element is a device. If it has exactly
828 * one child bus accept it nevertheless */
829 switch (dev->num_child_bus) {
830 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100831 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200832 return NULL;
833 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000834 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200835 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100836 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100837 if (!monitor_cur_is_qmp()) {
838 qbus_list_bus(dev);
839 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200840 return NULL;
841 }
842 }
843
844 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100845 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
846 assert(0);
847 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200848 }
849 pos += len;
850 bus = qbus_find_bus(dev, elem);
851 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100852 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100853 if (!monitor_cur_is_qmp()) {
854 qbus_list_bus(dev);
855 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200856 return NULL;
857 }
858 }
859}
860
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200861void qbus_create_inplace(BusState *bus, BusInfo *info,
862 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100863{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200864 char *buf;
865 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100866
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200867 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100868 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200869
870 if (name) {
871 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500872 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200873 } else if (parent && parent->id) {
874 /* parent device has id -> use it for bus name */
875 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500876 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200877 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
878 bus->name = buf;
879 } else {
880 /* no id -> use lowercase bus type for bus name */
881 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500882 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200883 len = snprintf(buf, len, "%s.%d", info->name,
884 parent ? parent->num_child_bus : 0);
885 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200886 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200887 bus->name = buf;
888 }
889
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200890 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100891 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000892 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200893 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900894 } else if (bus != main_system_bus) {
895 /* TODO: once all bus devices are qdevified,
896 only reset handler for main_system_bus should be registered here. */
897 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100898 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200899}
900
901BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
902{
903 BusState *bus;
904
Anthony Liguori7267c092011-08-20 22:09:37 -0500905 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200906 bus->qdev_allocated = 1;
907 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100908 return bus;
909}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100910
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900911static void main_system_bus_create(void)
912{
913 /* assign main_system_bus before qbus_create_inplace()
914 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500915 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900916 main_system_bus->qdev_allocated = 1;
917 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
918 "main-system-bus");
919}
920
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200921void qbus_free(BusState *bus)
922{
923 DeviceState *dev;
924
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200925 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200926 qdev_free(dev);
927 }
928 if (bus->parent) {
929 QLIST_REMOVE(bus, sibling);
930 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900931 } else {
932 assert(bus != main_system_bus); /* main_system_bus is never freed */
933 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200934 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500935 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200936 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500937 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200938 }
939}
940
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100941#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
942static void qbus_print(Monitor *mon, BusState *bus, int indent);
943
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200944static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
945 const char *prefix, int indent)
946{
947 char buf[64];
948
949 if (!props)
950 return;
951 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100952 /*
953 * TODO Properties without a print method are just for dirty
954 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
955 * marked for removal. The test props->info->print should be
956 * removed along with it.
957 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200958 if (props->info->print) {
959 props->info->print(dev, props, buf, sizeof(buf));
960 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
961 }
962 props++;
963 }
964}
965
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100966static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
967{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100968 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200969 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
970 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100971 indent += 2;
972 if (dev->num_gpio_in) {
973 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
974 }
975 if (dev->num_gpio_out) {
976 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
977 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200978 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
979 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200980 if (dev->parent_bus->info->print_dev)
981 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000982 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100983 qbus_print(mon, child, indent);
984 }
985}
986
987static void qbus_print(Monitor *mon, BusState *bus, int indent)
988{
989 struct DeviceState *dev;
990
991 qdev_printf("bus: %s\n", bus->name);
992 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200993 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200994 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100995 qdev_print(mon, dev, indent);
996 }
997}
998#undef qdev_printf
999
1000void do_info_qtree(Monitor *mon)
1001{
1002 if (main_system_bus)
1003 qbus_print(mon, main_system_bus, 0);
1004}
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001005
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +02001006void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001007{
1008 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001009
1010 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +01001011 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +02001012 }
1013}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001014
Markus Armbruster8bc27242010-02-10 20:52:01 +01001015int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001016{
1017 QemuOpts *opts;
1018
Gerd Hoffmann3329f072010-08-20 13:52:01 +02001019 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +01001020 if (!opts) {
1021 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +01001022 }
Markus Armbruster8bc27242010-02-10 20:52:01 +01001023 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
1024 qemu_opts_del(opts);
1025 return 0;
1026 }
1027 if (!qdev_device_add(opts)) {
1028 qemu_opts_del(opts);
1029 return -1;
1030 }
1031 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001032}
1033
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001034int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001035{
1036 const char *id = qdict_get_str(qdict, "id");
1037 DeviceState *dev;
1038
1039 dev = qdev_find_recursive(main_system_bus, id);
1040 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001041 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1042 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001043 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001044 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001045}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001046
1047static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1048{
1049 int l = 0;
1050
1051 if (dev && dev->parent_bus) {
1052 char *d;
1053 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1054 if (dev->parent_bus->info->get_fw_dev_path) {
1055 d = dev->parent_bus->info->get_fw_dev_path(dev);
1056 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001057 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001058 } else {
1059 l += snprintf(p + l, size - l, "%s", dev->info->name);
1060 }
1061 }
1062 l += snprintf(p + l , size - l, "/");
1063
1064 return l;
1065}
1066
1067char* qdev_get_fw_dev_path(DeviceState *dev)
1068{
1069 char path[128];
1070 int l;
1071
1072 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1073
1074 path[l-1] = '\0';
1075
1076 return strdup(path);
1077}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001078
Anthony Liguoricd34d662011-12-12 14:29:43 -06001079char *qdev_get_type(DeviceState *dev, Error **errp)
1080{
1081 return g_strdup(dev->info->name);
1082}
1083
Anthony Liguori85ed3032011-12-12 14:29:25 -06001084void qdev_ref(DeviceState *dev)
1085{
1086 dev->ref++;
1087}
1088
1089void qdev_unref(DeviceState *dev)
1090{
1091 g_assert(dev->ref > 0);
1092 dev->ref--;
1093}
Anthony Liguori44677de2011-12-12 14:29:26 -06001094
1095void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1096 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1097 DevicePropertyRelease *release,
1098 void *opaque, Error **errp)
1099{
1100 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1101
1102 prop->name = g_strdup(name);
1103 prop->type = g_strdup(type);
1104
1105 prop->get = get;
1106 prop->set = set;
1107 prop->release = release;
1108 prop->opaque = opaque;
1109
1110 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1111}
1112
1113static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1114{
1115 DeviceProperty *prop;
1116
1117 QTAILQ_FOREACH(prop, &dev->properties, node) {
1118 if (strcmp(prop->name, name) == 0) {
1119 return prop;
1120 }
1121 }
1122
1123 return NULL;
1124}
1125
1126void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1127 Error **errp)
1128{
1129 DeviceProperty *prop = qdev_property_find(dev, name);
1130
1131 if (prop == NULL) {
1132 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1133 return;
1134 }
1135
1136 if (!prop->get) {
1137 error_set(errp, QERR_PERMISSION_DENIED);
1138 } else {
1139 prop->get(dev, v, prop->opaque, name, errp);
1140 }
1141}
1142
1143void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1144 Error **errp)
1145{
1146 DeviceProperty *prop = qdev_property_find(dev, name);
1147
1148 if (prop == NULL) {
1149 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1150 return;
1151 }
1152
1153 if (!prop->set) {
1154 error_set(errp, QERR_PERMISSION_DENIED);
1155 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001156 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001157 }
1158}
1159
1160const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1161{
1162 DeviceProperty *prop = qdev_property_find(dev, name);
1163
1164 if (prop == NULL) {
1165 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1166 return NULL;
1167 }
1168
1169 return prop->type;
1170}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001171
1172/**
1173 * Legacy property handling
1174 */
1175
1176static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1177 const char *name, Error **errp)
1178{
1179 Property *prop = opaque;
1180
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001181 char buffer[1024];
1182 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001183
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001184 prop->info->print(dev, prop, buffer, sizeof(buffer));
1185 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001186}
1187
1188static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1189 const char *name, Error **errp)
1190{
1191 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001192 Error *local_err = NULL;
1193 char *ptr = NULL;
1194 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001195
1196 if (dev->state != DEV_STATE_CREATED) {
1197 error_set(errp, QERR_PERMISSION_DENIED);
1198 return;
1199 }
1200
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001201 visit_type_str(v, &ptr, name, &local_err);
1202 if (local_err) {
1203 error_propagate(errp, local_err);
1204 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001205 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001206
1207 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001208 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001209 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001210}
1211
1212/**
1213 * @qdev_add_legacy_property - adds a legacy property
1214 *
1215 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001216 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001217 *
1218 * Legacy properties are always processed as strings. The format of the string
1219 * depends on the property type.
1220 */
1221void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1222 Error **errp)
1223{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001224 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001225
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001226 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001227 type = g_strdup_printf("legacy<%s>",
1228 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001229
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001230 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001231 prop->info->print ? qdev_get_legacy_property : NULL,
1232 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001233 NULL,
1234 prop, errp);
1235
1236 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001237 g_free(name);
1238}
1239
1240/**
1241 * @qdev_property_add_static - add a @Property to a device.
1242 *
1243 * Static properties access data in a struct. The actual type of the
1244 * property and the field depends on the property type.
1245 */
1246void qdev_property_add_static(DeviceState *dev, Property *prop,
1247 Error **errp)
1248{
1249 qdev_property_add(dev, prop->name, prop->info->name,
1250 prop->info->get, prop->info->set,
1251 NULL,
1252 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001253}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001254
1255DeviceState *qdev_get_root(void)
1256{
1257 static DeviceState *qdev_root;
1258
1259 if (!qdev_root) {
1260 qdev_root = qdev_create(NULL, "container");
1261 qdev_init_nofail(qdev_root);
1262 }
1263
1264 return qdev_root;
1265}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001266
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001267static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1268 const char *name, Error **errp)
1269{
1270 DeviceState *child = opaque;
1271 gchar *path;
1272
1273 path = qdev_get_canonical_path(child);
1274 visit_type_str(v, &path, name, errp);
1275 g_free(path);
1276}
1277
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001278static void qdev_release_child_property(DeviceState *dev, const char *name,
1279 void *opaque)
1280{
1281 DeviceState *child = opaque;
1282
1283 qdev_unref(child);
1284}
1285
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001286void qdev_property_add_child(DeviceState *dev, const char *name,
1287 DeviceState *child, Error **errp)
1288{
1289 gchar *type;
1290
1291 type = g_strdup_printf("child<%s>", child->info->name);
1292
1293 qdev_property_add(dev, name, type, qdev_get_child_property,
Anthony Liguori024a6fb2012-01-13 07:45:55 -06001294 NULL, qdev_release_child_property,
1295 child, errp);
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001296
1297 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001298 g_assert(child->parent == NULL);
1299 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001300
1301 g_free(type);
1302}
1303
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001304static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1305 const char *name, Error **errp)
1306{
1307 DeviceState **child = opaque;
1308 gchar *path;
1309
1310 if (*child) {
1311 path = qdev_get_canonical_path(*child);
1312 visit_type_str(v, &path, name, errp);
1313 g_free(path);
1314 } else {
1315 path = (gchar *)"";
1316 visit_type_str(v, &path, name, errp);
1317 }
1318}
1319
1320static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1321 const char *name, Error **errp)
1322{
1323 DeviceState **child = opaque;
1324 bool ambiguous = false;
1325 const char *type;
1326 char *path;
1327
1328 type = qdev_property_get_type(dev, name, NULL);
1329
1330 visit_type_str(v, &path, name, errp);
1331
1332 if (*child) {
1333 qdev_unref(*child);
1334 }
1335
1336 if (strcmp(path, "") != 0) {
1337 DeviceState *target;
1338
1339 target = qdev_resolve_path(path, &ambiguous);
1340 if (target) {
1341 gchar *target_type;
1342
1343 target_type = g_strdup_printf("link<%s>", target->info->name);
1344 if (strcmp(target_type, type) == 0) {
1345 *child = target;
1346 qdev_ref(target);
1347 } else {
1348 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1349 }
1350
1351 g_free(target_type);
1352 } else {
1353 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1354 }
1355 } else {
1356 *child = NULL;
1357 }
1358
1359 g_free(path);
1360}
1361
1362void qdev_property_add_link(DeviceState *dev, const char *name,
1363 const char *type, DeviceState **child,
1364 Error **errp)
1365{
1366 gchar *full_type;
1367
1368 full_type = g_strdup_printf("link<%s>", type);
1369
1370 qdev_property_add(dev, name, full_type,
1371 qdev_get_link_property,
1372 qdev_set_link_property,
1373 NULL, child, errp);
1374
1375 g_free(full_type);
1376}
1377
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001378gchar *qdev_get_canonical_path(DeviceState *dev)
1379{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001380 DeviceState *root = qdev_get_root();
1381 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001382
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001383 while (dev != root) {
1384 DeviceProperty *prop = NULL;
1385
1386 g_assert(dev->parent != NULL);
1387
1388 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1389 if (!strstart(prop->type, "child<", NULL)) {
1390 continue;
1391 }
1392
1393 if (prop->opaque == dev) {
1394 if (path) {
1395 newpath = g_strdup_printf("%s/%s", prop->name, path);
1396 g_free(path);
1397 path = newpath;
1398 } else {
1399 path = g_strdup(prop->name);
1400 }
1401 break;
1402 }
1403 }
1404
1405 g_assert(prop != NULL);
1406
1407 dev = dev->parent;
1408 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001409
1410 newpath = g_strdup_printf("/%s", path);
1411 g_free(path);
1412
1413 return newpath;
1414}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001415
1416static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1417 gchar **parts,
1418 int index)
1419{
1420 DeviceProperty *prop;
1421 DeviceState *child;
1422
1423 if (parts[index] == NULL) {
1424 return parent;
1425 }
1426
1427 if (strcmp(parts[index], "") == 0) {
1428 return qdev_resolve_abs_path(parent, parts, index + 1);
1429 }
1430
1431 prop = qdev_property_find(parent, parts[index]);
1432 if (prop == NULL) {
1433 return NULL;
1434 }
1435
1436 child = NULL;
1437 if (strstart(prop->type, "link<", NULL)) {
1438 DeviceState **pchild = prop->opaque;
1439 if (*pchild) {
1440 child = *pchild;
1441 }
1442 } else if (strstart(prop->type, "child<", NULL)) {
1443 child = prop->opaque;
1444 }
1445
1446 if (!child) {
1447 return NULL;
1448 }
1449
1450 return qdev_resolve_abs_path(child, parts, index + 1);
1451}
1452
1453static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1454 gchar **parts,
1455 bool *ambiguous)
1456{
1457 DeviceState *dev;
1458 DeviceProperty *prop;
1459
1460 dev = qdev_resolve_abs_path(parent, parts, 0);
1461
1462 QTAILQ_FOREACH(prop, &parent->properties, node) {
1463 DeviceState *found;
1464
1465 if (!strstart(prop->type, "child<", NULL)) {
1466 continue;
1467 }
1468
1469 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1470 if (found) {
1471 if (dev) {
1472 if (ambiguous) {
1473 *ambiguous = true;
1474 }
1475 return NULL;
1476 }
1477 dev = found;
1478 }
1479
1480 if (ambiguous && *ambiguous) {
1481 return NULL;
1482 }
1483 }
1484
1485 return dev;
1486}
1487
1488DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1489{
1490 bool partial_path = true;
1491 DeviceState *dev;
1492 gchar **parts;
1493
1494 parts = g_strsplit(path, "/", 0);
1495 if (parts == NULL || parts[0] == NULL) {
1496 g_strfreev(parts);
1497 return qdev_get_root();
1498 }
1499
1500 if (strcmp(parts[0], "") == 0) {
1501 partial_path = false;
1502 }
1503
1504 if (partial_path) {
1505 if (ambiguous) {
1506 *ambiguous = false;
1507 }
1508 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1509 } else {
1510 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1511 }
1512
1513 g_strfreev(parts);
1514
1515 return dev;
1516}
1517
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001518typedef struct StringProperty
1519{
1520 char *(*get)(DeviceState *, Error **);
1521 void (*set)(DeviceState *, const char *, Error **);
1522} StringProperty;
1523
1524static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1525 const char *name, Error **errp)
1526{
1527 StringProperty *prop = opaque;
1528 char *value;
1529
1530 value = prop->get(dev, errp);
1531 if (value) {
1532 visit_type_str(v, &value, name, errp);
1533 g_free(value);
1534 }
1535}
1536
1537static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1538 const char *name, Error **errp)
1539{
1540 StringProperty *prop = opaque;
1541 char *value;
1542 Error *local_err = NULL;
1543
1544 visit_type_str(v, &value, name, &local_err);
1545 if (local_err) {
1546 error_propagate(errp, local_err);
1547 return;
1548 }
1549
1550 prop->set(dev, value, errp);
1551 g_free(value);
1552}
1553
1554static void qdev_property_release_str(DeviceState *dev, const char *name,
1555 void *opaque)
1556{
1557 StringProperty *prop = opaque;
1558 g_free(prop);
1559}
1560
1561void qdev_property_add_str(DeviceState *dev, const char *name,
1562 char *(*get)(DeviceState *, Error **),
1563 void (*set)(DeviceState *, const char *, Error **),
1564 Error **errp)
1565{
1566 StringProperty *prop = g_malloc0(sizeof(*prop));
1567
1568 prop->get = get;
1569 prop->set = set;
1570
1571 qdev_property_add(dev, name, "string",
1572 get ? qdev_property_get_str : NULL,
1573 set ? qdev_property_set_str : NULL,
1574 qdev_property_release_str,
1575 prop, errp);
1576}
Anthony Liguori1de81d22011-12-19 16:37:46 -06001577
1578void qdev_machine_init(void)
1579{
1580 qdev_get_peripheral_anon();
1581 qdev_get_peripheral();
1582}
Anthony Liguori32fea402011-12-16 14:34:46 -06001583
1584static TypeInfo device_type_info = {
1585 .name = TYPE_DEVICE,
1586 .parent = TYPE_OBJECT,
1587 .instance_size = sizeof(DeviceState),
1588 .abstract = true,
1589 .class_size = sizeof(DeviceClass),
1590};
1591
1592static void init_qdev(void)
1593{
1594 type_register_static(&device_type_info);
1595}
1596
1597device_init(init_qdev);