blob: c020a6f39241c321139b83b720da9274d9a651b8 [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{
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020050 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020051 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010052
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020053 info->next = device_info_list;
54 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010055}
56
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020057static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
58{
59 DeviceInfo *info;
60
Gerd Hoffmann3320e562009-07-15 13:43:33 +020061 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020062 for (info = device_info_list; info != NULL; info = info->next) {
63 if (bus_info && info->bus_info != bus_info)
64 continue;
65 if (strcmp(info->name, name) != 0)
66 continue;
67 return info;
68 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +020069
70 /* failing that check the aliases */
71 for (info = device_info_list; info != NULL; info = info->next) {
72 if (bus_info && info->bus_info != bus_info)
73 continue;
74 if (!info->alias)
75 continue;
76 if (strcmp(info->alias, name) != 0)
77 continue;
78 return info;
79 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020080 return NULL;
81}
82
Markus Armbruster0c175422010-02-19 19:12:18 +010083static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010084{
Paul Brookaae94602009-05-14 22:35:06 +010085 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -060086 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010087
Markus Armbruster0c175422010-02-19 19:12:18 +010088 assert(bus->info == info->bus_info);
Anthony Liguori7267c092011-08-20 22:09:37 -050089 dev = g_malloc0(info->size);
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020090 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +010091 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020092 qdev_prop_set_defaults(dev, dev->info->props);
93 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010094 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +020095 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020096 if (qdev_hotplug) {
97 assert(bus->allow_hotplug);
98 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070099 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200100 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200101 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600102 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200103 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600104
105 for (prop = dev->info->props; prop && prop->name; prop++) {
106 qdev_property_add_legacy(dev, prop, NULL);
107 }
108
109 for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
110 qdev_property_add_legacy(dev, prop, NULL);
111 }
112
Anthony Liguoricd34d662011-12-12 14:29:43 -0600113 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
114
Paul Brookaae94602009-05-14 22:35:06 +0100115 return dev;
116}
117
Markus Armbruster0c175422010-02-19 19:12:18 +0100118/* Create a new device. This only initializes the device state structure
119 and allows properties to be set. qdev_init should be called to
120 initialize the actual device emulation. */
121DeviceState *qdev_create(BusState *bus, const char *name)
122{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000123 DeviceState *dev;
124
125 dev = qdev_try_create(bus, name);
126 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100127 if (bus) {
128 hw_error("Unknown device '%s' for bus '%s'\n", name,
129 bus->info->name);
130 } else {
131 hw_error("Unknown device '%s' for default sysbus\n", name);
132 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000133 }
134
135 return dev;
136}
137
138DeviceState *qdev_try_create(BusState *bus, const char *name)
139{
Markus Armbruster0c175422010-02-19 19:12:18 +0100140 DeviceInfo *info;
141
142 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100143 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100144 }
145
146 info = qdev_find_info(bus->info, name);
147 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000148 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100149 }
150
151 return qdev_create_from_info(bus, info);
152}
153
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100154static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200155{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100156 error_printf("name \"%s\", bus %s",
157 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200158 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100159 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200160 }
161 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100162 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200163 }
164 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100165 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200166 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100167 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200168}
169
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200170static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200171{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200172 DeviceState *dev = opaque;
173
174 if (strcmp(name, "driver") == 0)
175 return 0;
176 if (strcmp(name, "bus") == 0)
177 return 0;
178
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100179 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200180 return -1;
181 }
182 return 0;
183}
184
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100185int qdev_device_help(QemuOpts *opts)
186{
187 const char *driver;
188 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100189 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100190
191 driver = qemu_opt_get(opts, "driver");
192 if (driver && !strcmp(driver, "?")) {
193 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100194 if (info->no_user) {
195 continue; /* not available, don't show */
196 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100197 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100198 }
199 return 1;
200 }
201
Markus Armbruster542379f2011-11-08 11:00:38 +0100202 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100203 return 0;
204 }
205
206 info = qdev_find_info(NULL, driver);
207 if (!info) {
208 return 0;
209 }
210
211 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100212 /*
213 * TODO Properties without a parser are just for dirty hacks.
214 * qdev_prop_ptr is the only such PropertyInfo. It's marked
215 * for removal. This conditional should be removed along with
216 * it.
217 */
218 if (!prop->info->parse) {
219 continue; /* no way to set it, don't show */
220 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100221 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100222 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200223 for (prop = info->bus_info->props; prop && prop->name; prop++) {
224 if (!prop->info->parse) {
225 continue; /* no way to set it, don't show */
226 }
227 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
228 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100229 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100230}
231
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600232static DeviceState *qdev_get_peripheral(void)
233{
234 static DeviceState *dev;
235
236 if (dev == NULL) {
237 dev = qdev_create(NULL, "container");
238 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
239 qdev_init_nofail(dev);
240 }
241
242 return dev;
243}
244
Anthony Liguori8eb02832011-12-12 14:29:37 -0600245static DeviceState *qdev_get_peripheral_anon(void)
246{
247 static DeviceState *dev;
248
249 if (dev == NULL) {
250 dev = qdev_create(NULL, "container");
251 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
252 qdev_init_nofail(dev);
253 }
254
255 return dev;
256}
257
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200258DeviceState *qdev_device_add(QemuOpts *opts)
259{
260 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200261 DeviceInfo *info;
262 DeviceState *qdev;
263 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200264
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200265 driver = qemu_opt_get(opts, "driver");
266 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100267 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200268 return NULL;
269 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200270
271 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200272 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100273 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100274 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100275 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200276 return NULL;
277 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200278
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200279 /* find bus */
280 path = qemu_opt_get(opts, "bus");
281 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200282 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100283 if (!bus) {
284 return NULL;
285 }
286 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100287 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
288 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100289 return NULL;
290 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200291 } else {
292 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100293 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100294 qerror_report(QERR_NO_BUS_FOR_DEVICE,
295 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100296 return NULL;
297 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200298 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200299 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100300 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200301 return NULL;
302 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200303
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200304 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100305 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200306 id = qemu_opts_id(opts);
307 if (id) {
308 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600309 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600310 } else {
311 static int anon_count;
312 gchar *name = g_strdup_printf("device[%d]", anon_count++);
313 qdev_property_add_child(qdev_get_peripheral_anon(), name,
314 qdev, NULL);
315 g_free(name);
316 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200317 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
318 qdev_free(qdev);
319 return NULL;
320 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200321 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100322 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200323 return NULL;
324 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200325 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200326 return qdev;
327}
328
Paul Brookaae94602009-05-14 22:35:06 +0100329/* Initialize a device. Device properties should be set before calling
330 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200331 calling this function.
332 On failure, destroy the device and return negative value.
333 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200334int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100335{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200336 int rc;
337
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200338 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200339 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200340 if (rc < 0) {
341 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200342 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200343 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200344 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600345 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200346 dev->instance_id_alias,
347 dev->alias_required_for_version);
348 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200349 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200350 if (dev->hotplugged && dev->info->reset) {
351 dev->info->reset(dev);
352 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200353 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100354}
355
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200356void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
357 int required_for_version)
358{
359 assert(dev->state == DEV_STATE_CREATED);
360 dev->instance_id_alias = alias_id;
361 dev->alias_required_for_version = required_for_version;
362}
363
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200364int qdev_unplug(DeviceState *dev)
365{
366 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100367 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200368 return -1;
369 }
Amit Shah593831d2009-11-02 14:56:41 +0530370 assert(dev->info->unplug != NULL);
371
Anthony Liguori85ed3032011-12-12 14:29:25 -0600372 if (dev->ref != 0) {
373 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
374 return -1;
375 }
376
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700377 qdev_hot_removed = true;
378
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200379 return dev->info->unplug(dev);
380}
381
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900382static int qdev_reset_one(DeviceState *dev, void *opaque)
383{
384 if (dev->info->reset) {
385 dev->info->reset(dev);
386 }
387
388 return 0;
389}
390
391BusState *sysbus_get_default(void)
392{
Stefan Weil68694892010-12-16 19:33:22 +0100393 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900394 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100395 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900396 return main_system_bus;
397}
398
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900399static int qbus_reset_one(BusState *bus, void *opaque)
400{
401 if (bus->info->reset) {
402 return bus->info->reset(bus);
403 }
404 return 0;
405}
406
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900407void qdev_reset_all(DeviceState *dev)
408{
409 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
410}
411
Isaku Yamahata80376c32010-12-20 14:33:35 +0900412void qbus_reset_all_fn(void *opaque)
413{
414 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200415 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900416}
417
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200418/* can be used as ->unplug() callback for the simple cases */
419int qdev_simple_unplug_cb(DeviceState *dev)
420{
421 /* just zap it */
422 qdev_free(dev);
423 return 0;
424}
425
Michael Tokarev3b29a102011-04-06 17:51:59 +0400426
427/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200428 returning an error value. This is okay during machine creation.
429 Don't use for hotplug, because there callers need to recover from
430 failure. Exception: if you know the device's init() callback can't
431 fail, then qdev_init_nofail() can't fail either, and is therefore
432 usable even then. But relying on the device implementation that
433 way is somewhat unclean, and best avoided. */
434void qdev_init_nofail(DeviceState *dev)
435{
436 DeviceInfo *info = dev->info;
437
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200438 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200439 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200440 exit(1);
441 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200442}
443
Anthony Liguori44677de2011-12-12 14:29:26 -0600444static void qdev_property_del_all(DeviceState *dev)
445{
446 while (!QTAILQ_EMPTY(&dev->properties)) {
447 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
448
449 QTAILQ_REMOVE(&dev->properties, prop, node);
450
451 if (prop->release) {
452 prop->release(dev, prop->name, prop->opaque);
453 }
454
455 g_free(prop->name);
456 g_free(prop->type);
457 g_free(prop);
458 }
459}
460
Paul Brook02e2da42009-05-23 00:05:19 +0100461/* Unlink device from bus and free the structure. */
462void qdev_free(DeviceState *dev)
463{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200464 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200465 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200466
Anthony Liguori44677de2011-12-12 14:29:26 -0600467 qdev_property_del_all(dev);
468
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200469 if (dev->state == DEV_STATE_INITIALIZED) {
470 while (dev->num_child_bus) {
471 bus = QLIST_FIRST(&dev->child_bus);
472 qbus_free(bus);
473 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200474 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600475 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200476 if (dev->info->exit)
477 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200478 if (dev->opts)
479 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200480 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200481 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200482 for (prop = dev->info->props; prop && prop->name; prop++) {
483 if (prop->info->free) {
484 prop->info->free(dev, prop);
485 }
486 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500487 g_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100488}
489
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200490void qdev_machine_creation_done(void)
491{
492 /*
493 * ok, initial machine setup is done, starting from now we can
494 * only create hotpluggable devices
495 */
496 qdev_hotplug = 1;
497}
498
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700499bool qdev_machine_modified(void)
500{
501 return qdev_hot_added || qdev_hot_removed;
502}
503
Paul Brookaae94602009-05-14 22:35:06 +0100504/* Get a character (serial) device interface. */
505CharDriverState *qdev_init_chardev(DeviceState *dev)
506{
507 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530508
509 /* FIXME: This function needs to go away: use chardev properties! */
510 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100511}
512
Paul Brook02e2da42009-05-23 00:05:19 +0100513BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100514{
Paul Brook02e2da42009-05-23 00:05:19 +0100515 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100516}
517
Paul Brookaae94602009-05-14 22:35:06 +0100518void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
519{
520 assert(dev->num_gpio_in == 0);
521 dev->num_gpio_in = n;
522 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
523}
524
525void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
526{
527 assert(dev->num_gpio_out == 0);
528 dev->num_gpio_out = n;
529 dev->gpio_out = pins;
530}
531
532qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
533{
534 assert(n >= 0 && n < dev->num_gpio_in);
535 return dev->gpio_in[n];
536}
537
538void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
539{
540 assert(n >= 0 && n < dev->num_gpio_out);
541 dev->gpio_out[n] = pin;
542}
543
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200544void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
545{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200546 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200547 if (nd->vlan)
548 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
549 if (nd->netdev)
550 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530551 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200552 qdev_prop_exists(dev, "vectors")) {
553 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
554 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100555 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200556}
557
Paul Brook02e2da42009-05-23 00:05:19 +0100558BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100559{
Paul Brook02e2da42009-05-23 00:05:19 +0100560 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100561
Blue Swirl72cf2d42009-09-12 07:36:22 +0000562 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100563 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100564 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100565 }
566 }
567 return NULL;
568}
569
Anthony Liguori81699d82010-11-19 18:55:58 +0900570int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
571 qbus_walkerfn *busfn, void *opaque)
572{
573 DeviceState *dev;
574 int err;
575
576 if (busfn) {
577 err = busfn(bus, opaque);
578 if (err) {
579 return err;
580 }
581 }
582
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200583 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900584 err = qdev_walk_children(dev, devfn, busfn, opaque);
585 if (err < 0) {
586 return err;
587 }
588 }
589
590 return 0;
591}
592
593int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
594 qbus_walkerfn *busfn, void *opaque)
595{
596 BusState *bus;
597 int err;
598
599 if (devfn) {
600 err = devfn(dev, opaque);
601 if (err) {
602 return err;
603 }
604 }
605
606 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
607 err = qbus_walk_children(bus, devfn, busfn, opaque);
608 if (err < 0) {
609 return err;
610 }
611 }
612
613 return 0;
614}
615
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200616static BusState *qbus_find_recursive(BusState *bus, const char *name,
617 const BusInfo *info)
618{
619 DeviceState *dev;
620 BusState *child, *ret;
621 int match = 1;
622
623 if (name && (strcmp(bus->name, name) != 0)) {
624 match = 0;
625 }
626 if (info && (bus->info != info)) {
627 match = 0;
628 }
629 if (match) {
630 return bus;
631 }
632
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200633 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000634 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200635 ret = qbus_find_recursive(child, name, info);
636 if (ret) {
637 return ret;
638 }
639 }
640 }
641 return NULL;
642}
643
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900644DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200645{
646 DeviceState *dev, *ret;
647 BusState *child;
648
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200649 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200650 if (dev->id && strcmp(dev->id, id) == 0)
651 return dev;
652 QLIST_FOREACH(child, &dev->child_bus, sibling) {
653 ret = qdev_find_recursive(child, id);
654 if (ret) {
655 return ret;
656 }
657 }
658 }
659 return NULL;
660}
661
Markus Armbruster53db16b2010-02-18 18:55:59 +0100662static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200663{
664 BusState *child;
665 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200666
Markus Armbruster53db16b2010-02-18 18:55:59 +0100667 error_printf("child busses at \"%s\":",
668 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000669 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100670 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200671 sep = ", ";
672 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100673 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200674}
675
Markus Armbruster53db16b2010-02-18 18:55:59 +0100676static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200677{
678 DeviceState *dev;
679 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200680
Markus Armbruster53db16b2010-02-18 18:55:59 +0100681 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200682 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100683 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200684 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100685 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200686 sep = ", ";
687 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100688 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200689}
690
691static BusState *qbus_find_bus(DeviceState *dev, char *elem)
692{
693 BusState *child;
694
Blue Swirl72cf2d42009-09-12 07:36:22 +0000695 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200696 if (strcmp(child->name, elem) == 0) {
697 return child;
698 }
699 }
700 return NULL;
701}
702
703static DeviceState *qbus_find_dev(BusState *bus, char *elem)
704{
705 DeviceState *dev;
706
707 /*
708 * try to match in order:
709 * (1) instance id, if present
710 * (2) driver name
711 * (3) driver alias, if present
712 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200713 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200714 if (dev->id && strcmp(dev->id, elem) == 0) {
715 return dev;
716 }
717 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200718 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200719 if (strcmp(dev->info->name, elem) == 0) {
720 return dev;
721 }
722 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200723 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200724 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
725 return dev;
726 }
727 }
728 return NULL;
729}
730
731static BusState *qbus_find(const char *path)
732{
733 DeviceState *dev;
734 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100735 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200736 int pos, len;
737
738 /* find start element */
739 if (path[0] == '/') {
740 bus = main_system_bus;
741 pos = 0;
742 } else {
743 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100744 assert(!path[0]);
745 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200746 }
747 bus = qbus_find_recursive(main_system_bus, elem, NULL);
748 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100749 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200750 return NULL;
751 }
752 pos = len;
753 }
754
755 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100756 assert(path[pos] == '/' || !path[pos]);
757 while (path[pos] == '/') {
758 pos++;
759 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200760 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200761 return bus;
762 }
763
764 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100765 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
766 assert(0);
767 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200768 }
769 pos += len;
770 dev = qbus_find_dev(bus, elem);
771 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100772 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100773 if (!monitor_cur_is_qmp()) {
774 qbus_list_dev(bus);
775 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200776 return NULL;
777 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100778
779 assert(path[pos] == '/' || !path[pos]);
780 while (path[pos] == '/') {
781 pos++;
782 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200783 if (path[pos] == '\0') {
784 /* last specified element is a device. If it has exactly
785 * one child bus accept it nevertheless */
786 switch (dev->num_child_bus) {
787 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100788 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200789 return NULL;
790 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000791 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200792 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100793 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100794 if (!monitor_cur_is_qmp()) {
795 qbus_list_bus(dev);
796 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200797 return NULL;
798 }
799 }
800
801 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100802 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
803 assert(0);
804 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200805 }
806 pos += len;
807 bus = qbus_find_bus(dev, elem);
808 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100809 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100810 if (!monitor_cur_is_qmp()) {
811 qbus_list_bus(dev);
812 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200813 return NULL;
814 }
815 }
816}
817
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200818void qbus_create_inplace(BusState *bus, BusInfo *info,
819 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100820{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200821 char *buf;
822 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100823
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200824 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100825 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200826
827 if (name) {
828 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500829 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200830 } else if (parent && parent->id) {
831 /* parent device has id -> use it for bus name */
832 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500833 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200834 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
835 bus->name = buf;
836 } else {
837 /* no id -> use lowercase bus type for bus name */
838 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500839 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200840 len = snprintf(buf, len, "%s.%d", info->name,
841 parent ? parent->num_child_bus : 0);
842 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200843 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200844 bus->name = buf;
845 }
846
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200847 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100848 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000849 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200850 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900851 } else if (bus != main_system_bus) {
852 /* TODO: once all bus devices are qdevified,
853 only reset handler for main_system_bus should be registered here. */
854 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100855 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200856}
857
858BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
859{
860 BusState *bus;
861
Anthony Liguori7267c092011-08-20 22:09:37 -0500862 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200863 bus->qdev_allocated = 1;
864 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100865 return bus;
866}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100867
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900868static void main_system_bus_create(void)
869{
870 /* assign main_system_bus before qbus_create_inplace()
871 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500872 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900873 main_system_bus->qdev_allocated = 1;
874 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
875 "main-system-bus");
876}
877
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200878void qbus_free(BusState *bus)
879{
880 DeviceState *dev;
881
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200882 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200883 qdev_free(dev);
884 }
885 if (bus->parent) {
886 QLIST_REMOVE(bus, sibling);
887 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900888 } else {
889 assert(bus != main_system_bus); /* main_system_bus is never freed */
890 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200891 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500892 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200893 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500894 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200895 }
896}
897
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100898#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
899static void qbus_print(Monitor *mon, BusState *bus, int indent);
900
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200901static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
902 const char *prefix, int indent)
903{
904 char buf[64];
905
906 if (!props)
907 return;
908 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100909 /*
910 * TODO Properties without a print method are just for dirty
911 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
912 * marked for removal. The test props->info->print should be
913 * removed along with it.
914 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200915 if (props->info->print) {
916 props->info->print(dev, props, buf, sizeof(buf));
917 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
918 }
919 props++;
920 }
921}
922
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100923static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
924{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100925 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200926 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
927 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100928 indent += 2;
929 if (dev->num_gpio_in) {
930 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
931 }
932 if (dev->num_gpio_out) {
933 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
934 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200935 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
936 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200937 if (dev->parent_bus->info->print_dev)
938 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000939 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100940 qbus_print(mon, child, indent);
941 }
942}
943
944static void qbus_print(Monitor *mon, BusState *bus, int indent)
945{
946 struct DeviceState *dev;
947
948 qdev_printf("bus: %s\n", bus->name);
949 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200950 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200951 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100952 qdev_print(mon, dev, indent);
953 }
954}
955#undef qdev_printf
956
957void do_info_qtree(Monitor *mon)
958{
959 if (main_system_bus)
960 qbus_print(mon, main_system_bus, 0);
961}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200962
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200963void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200964{
965 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200966
967 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100968 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200969 }
970}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200971
Markus Armbruster8bc27242010-02-10 20:52:01 +0100972int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200973{
974 QemuOpts *opts;
975
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200976 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100977 if (!opts) {
978 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100979 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100980 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
981 qemu_opts_del(opts);
982 return 0;
983 }
984 if (!qdev_device_add(opts)) {
985 qemu_opts_del(opts);
986 return -1;
987 }
988 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200989}
990
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100991int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200992{
993 const char *id = qdict_get_str(qdict, "id");
994 DeviceState *dev;
995
996 dev = qdev_find_recursive(main_system_bus, id);
997 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100998 qerror_report(QERR_DEVICE_NOT_FOUND, id);
999 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001000 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001001 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001002}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001003
1004static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1005{
1006 int l = 0;
1007
1008 if (dev && dev->parent_bus) {
1009 char *d;
1010 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1011 if (dev->parent_bus->info->get_fw_dev_path) {
1012 d = dev->parent_bus->info->get_fw_dev_path(dev);
1013 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001014 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001015 } else {
1016 l += snprintf(p + l, size - l, "%s", dev->info->name);
1017 }
1018 }
1019 l += snprintf(p + l , size - l, "/");
1020
1021 return l;
1022}
1023
1024char* qdev_get_fw_dev_path(DeviceState *dev)
1025{
1026 char path[128];
1027 int l;
1028
1029 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1030
1031 path[l-1] = '\0';
1032
1033 return strdup(path);
1034}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001035
Anthony Liguoricd34d662011-12-12 14:29:43 -06001036char *qdev_get_type(DeviceState *dev, Error **errp)
1037{
1038 return g_strdup(dev->info->name);
1039}
1040
Anthony Liguori85ed3032011-12-12 14:29:25 -06001041void qdev_ref(DeviceState *dev)
1042{
1043 dev->ref++;
1044}
1045
1046void qdev_unref(DeviceState *dev)
1047{
1048 g_assert(dev->ref > 0);
1049 dev->ref--;
1050}
Anthony Liguori44677de2011-12-12 14:29:26 -06001051
1052void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1053 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1054 DevicePropertyRelease *release,
1055 void *opaque, Error **errp)
1056{
1057 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1058
1059 prop->name = g_strdup(name);
1060 prop->type = g_strdup(type);
1061
1062 prop->get = get;
1063 prop->set = set;
1064 prop->release = release;
1065 prop->opaque = opaque;
1066
1067 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1068}
1069
1070static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1071{
1072 DeviceProperty *prop;
1073
1074 QTAILQ_FOREACH(prop, &dev->properties, node) {
1075 if (strcmp(prop->name, name) == 0) {
1076 return prop;
1077 }
1078 }
1079
1080 return NULL;
1081}
1082
1083void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1084 Error **errp)
1085{
1086 DeviceProperty *prop = qdev_property_find(dev, name);
1087
1088 if (prop == NULL) {
1089 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1090 return;
1091 }
1092
1093 if (!prop->get) {
1094 error_set(errp, QERR_PERMISSION_DENIED);
1095 } else {
1096 prop->get(dev, v, prop->opaque, name, errp);
1097 }
1098}
1099
1100void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1101 Error **errp)
1102{
1103 DeviceProperty *prop = qdev_property_find(dev, name);
1104
1105 if (prop == NULL) {
1106 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1107 return;
1108 }
1109
1110 if (!prop->set) {
1111 error_set(errp, QERR_PERMISSION_DENIED);
1112 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001113 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001114 }
1115}
1116
1117const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1118{
1119 DeviceProperty *prop = qdev_property_find(dev, name);
1120
1121 if (prop == NULL) {
1122 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1123 return NULL;
1124 }
1125
1126 return prop->type;
1127}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001128
1129/**
1130 * Legacy property handling
1131 */
1132
1133static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1134 const char *name, Error **errp)
1135{
1136 Property *prop = opaque;
1137
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001138 char buffer[1024];
1139 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001140
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001141 prop->info->print(dev, prop, buffer, sizeof(buffer));
1142 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001143}
1144
1145static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1146 const char *name, Error **errp)
1147{
1148 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001149 Error *local_err = NULL;
1150 char *ptr = NULL;
1151 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001152
1153 if (dev->state != DEV_STATE_CREATED) {
1154 error_set(errp, QERR_PERMISSION_DENIED);
1155 return;
1156 }
1157
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001158 visit_type_str(v, &ptr, name, &local_err);
1159 if (local_err) {
1160 error_propagate(errp, local_err);
1161 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001162 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001163
1164 ret = prop->info->parse(dev, prop, ptr);
1165 if (ret != 0) {
1166 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
1167 name, prop->info->name);
1168 }
1169 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001170}
1171
1172/**
1173 * @qdev_add_legacy_property - adds a legacy property
1174 *
1175 * Do not use this is new code! Properties added through this interface will
1176 * be given types in the "legacy<>" type namespace.
1177 *
1178 * Legacy properties are always processed as strings. The format of the string
1179 * depends on the property type.
1180 */
1181void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1182 Error **errp)
1183{
1184 gchar *type;
1185
1186 type = g_strdup_printf("legacy<%s>", prop->info->name);
1187
1188 qdev_property_add(dev, prop->name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001189 prop->info->print ? qdev_get_legacy_property : NULL,
1190 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001191 NULL,
1192 prop, errp);
1193
1194 g_free(type);
1195}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001196
1197DeviceState *qdev_get_root(void)
1198{
1199 static DeviceState *qdev_root;
1200
1201 if (!qdev_root) {
1202 qdev_root = qdev_create(NULL, "container");
1203 qdev_init_nofail(qdev_root);
1204 }
1205
1206 return qdev_root;
1207}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001208
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001209static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1210 const char *name, Error **errp)
1211{
1212 DeviceState *child = opaque;
1213 gchar *path;
1214
1215 path = qdev_get_canonical_path(child);
1216 visit_type_str(v, &path, name, errp);
1217 g_free(path);
1218}
1219
1220void qdev_property_add_child(DeviceState *dev, const char *name,
1221 DeviceState *child, Error **errp)
1222{
1223 gchar *type;
1224
1225 type = g_strdup_printf("child<%s>", child->info->name);
1226
1227 qdev_property_add(dev, name, type, qdev_get_child_property,
1228 NULL, NULL, child, errp);
1229
1230 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001231 g_assert(child->parent == NULL);
1232 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001233
1234 g_free(type);
1235}
1236
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001237static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1238 const char *name, Error **errp)
1239{
1240 DeviceState **child = opaque;
1241 gchar *path;
1242
1243 if (*child) {
1244 path = qdev_get_canonical_path(*child);
1245 visit_type_str(v, &path, name, errp);
1246 g_free(path);
1247 } else {
1248 path = (gchar *)"";
1249 visit_type_str(v, &path, name, errp);
1250 }
1251}
1252
1253static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1254 const char *name, Error **errp)
1255{
1256 DeviceState **child = opaque;
1257 bool ambiguous = false;
1258 const char *type;
1259 char *path;
1260
1261 type = qdev_property_get_type(dev, name, NULL);
1262
1263 visit_type_str(v, &path, name, errp);
1264
1265 if (*child) {
1266 qdev_unref(*child);
1267 }
1268
1269 if (strcmp(path, "") != 0) {
1270 DeviceState *target;
1271
1272 target = qdev_resolve_path(path, &ambiguous);
1273 if (target) {
1274 gchar *target_type;
1275
1276 target_type = g_strdup_printf("link<%s>", target->info->name);
1277 if (strcmp(target_type, type) == 0) {
1278 *child = target;
1279 qdev_ref(target);
1280 } else {
1281 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1282 }
1283
1284 g_free(target_type);
1285 } else {
1286 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1287 }
1288 } else {
1289 *child = NULL;
1290 }
1291
1292 g_free(path);
1293}
1294
1295void qdev_property_add_link(DeviceState *dev, const char *name,
1296 const char *type, DeviceState **child,
1297 Error **errp)
1298{
1299 gchar *full_type;
1300
1301 full_type = g_strdup_printf("link<%s>", type);
1302
1303 qdev_property_add(dev, name, full_type,
1304 qdev_get_link_property,
1305 qdev_set_link_property,
1306 NULL, child, errp);
1307
1308 g_free(full_type);
1309}
1310
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001311gchar *qdev_get_canonical_path(DeviceState *dev)
1312{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001313 DeviceState *root = qdev_get_root();
1314 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001315
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001316 while (dev != root) {
1317 DeviceProperty *prop = NULL;
1318
1319 g_assert(dev->parent != NULL);
1320
1321 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1322 if (!strstart(prop->type, "child<", NULL)) {
1323 continue;
1324 }
1325
1326 if (prop->opaque == dev) {
1327 if (path) {
1328 newpath = g_strdup_printf("%s/%s", prop->name, path);
1329 g_free(path);
1330 path = newpath;
1331 } else {
1332 path = g_strdup(prop->name);
1333 }
1334 break;
1335 }
1336 }
1337
1338 g_assert(prop != NULL);
1339
1340 dev = dev->parent;
1341 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001342
1343 newpath = g_strdup_printf("/%s", path);
1344 g_free(path);
1345
1346 return newpath;
1347}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001348
1349static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1350 gchar **parts,
1351 int index)
1352{
1353 DeviceProperty *prop;
1354 DeviceState *child;
1355
1356 if (parts[index] == NULL) {
1357 return parent;
1358 }
1359
1360 if (strcmp(parts[index], "") == 0) {
1361 return qdev_resolve_abs_path(parent, parts, index + 1);
1362 }
1363
1364 prop = qdev_property_find(parent, parts[index]);
1365 if (prop == NULL) {
1366 return NULL;
1367 }
1368
1369 child = NULL;
1370 if (strstart(prop->type, "link<", NULL)) {
1371 DeviceState **pchild = prop->opaque;
1372 if (*pchild) {
1373 child = *pchild;
1374 }
1375 } else if (strstart(prop->type, "child<", NULL)) {
1376 child = prop->opaque;
1377 }
1378
1379 if (!child) {
1380 return NULL;
1381 }
1382
1383 return qdev_resolve_abs_path(child, parts, index + 1);
1384}
1385
1386static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1387 gchar **parts,
1388 bool *ambiguous)
1389{
1390 DeviceState *dev;
1391 DeviceProperty *prop;
1392
1393 dev = qdev_resolve_abs_path(parent, parts, 0);
1394
1395 QTAILQ_FOREACH(prop, &parent->properties, node) {
1396 DeviceState *found;
1397
1398 if (!strstart(prop->type, "child<", NULL)) {
1399 continue;
1400 }
1401
1402 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1403 if (found) {
1404 if (dev) {
1405 if (ambiguous) {
1406 *ambiguous = true;
1407 }
1408 return NULL;
1409 }
1410 dev = found;
1411 }
1412
1413 if (ambiguous && *ambiguous) {
1414 return NULL;
1415 }
1416 }
1417
1418 return dev;
1419}
1420
1421DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1422{
1423 bool partial_path = true;
1424 DeviceState *dev;
1425 gchar **parts;
1426
1427 parts = g_strsplit(path, "/", 0);
1428 if (parts == NULL || parts[0] == NULL) {
1429 g_strfreev(parts);
1430 return qdev_get_root();
1431 }
1432
1433 if (strcmp(parts[0], "") == 0) {
1434 partial_path = false;
1435 }
1436
1437 if (partial_path) {
1438 if (ambiguous) {
1439 *ambiguous = false;
1440 }
1441 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1442 } else {
1443 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1444 }
1445
1446 g_strfreev(parts);
1447
1448 return dev;
1449}
1450
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001451typedef struct StringProperty
1452{
1453 char *(*get)(DeviceState *, Error **);
1454 void (*set)(DeviceState *, const char *, Error **);
1455} StringProperty;
1456
1457static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1458 const char *name, Error **errp)
1459{
1460 StringProperty *prop = opaque;
1461 char *value;
1462
1463 value = prop->get(dev, errp);
1464 if (value) {
1465 visit_type_str(v, &value, name, errp);
1466 g_free(value);
1467 }
1468}
1469
1470static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1471 const char *name, Error **errp)
1472{
1473 StringProperty *prop = opaque;
1474 char *value;
1475 Error *local_err = NULL;
1476
1477 visit_type_str(v, &value, name, &local_err);
1478 if (local_err) {
1479 error_propagate(errp, local_err);
1480 return;
1481 }
1482
1483 prop->set(dev, value, errp);
1484 g_free(value);
1485}
1486
1487static void qdev_property_release_str(DeviceState *dev, const char *name,
1488 void *opaque)
1489{
1490 StringProperty *prop = opaque;
1491 g_free(prop);
1492}
1493
1494void qdev_property_add_str(DeviceState *dev, const char *name,
1495 char *(*get)(DeviceState *, Error **),
1496 void (*set)(DeviceState *, const char *, Error **),
1497 Error **errp)
1498{
1499 StringProperty *prop = g_malloc0(sizeof(*prop));
1500
1501 prop->get = get;
1502 prop->set = set;
1503
1504 qdev_property_add(dev, name, "string",
1505 get ? qdev_property_get_str : NULL,
1506 set ? qdev_property_set_str : NULL,
1507 qdev_property_release_str,
1508 prop, errp);
1509}