blob: 83913c72f21198199316aa73af7441c1a3ee26eb [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 {
1113 prop->set(dev, prop->opaque, v, name, errp);
1114 }
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
1138 if (prop->info->print) {
1139 char buffer[1024];
1140 char *ptr = buffer;
1141
1142 prop->info->print(dev, prop, buffer, sizeof(buffer));
1143 visit_type_str(v, &ptr, name, errp);
1144 } else {
1145 error_set(errp, QERR_PERMISSION_DENIED);
1146 }
1147}
1148
1149static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1150 const char *name, Error **errp)
1151{
1152 Property *prop = opaque;
1153
1154 if (dev->state != DEV_STATE_CREATED) {
1155 error_set(errp, QERR_PERMISSION_DENIED);
1156 return;
1157 }
1158
1159 if (prop->info->parse) {
1160 Error *local_err = NULL;
1161 char *ptr = NULL;
1162
1163 visit_type_str(v, &ptr, name, &local_err);
1164 if (!local_err) {
1165 int ret;
1166 ret = prop->info->parse(dev, prop, ptr);
1167 if (ret != 0) {
1168 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
1169 name, prop->info->name);
1170 }
1171 g_free(ptr);
1172 } else {
1173 error_propagate(errp, local_err);
1174 }
1175 } else {
1176 error_set(errp, QERR_PERMISSION_DENIED);
1177 }
1178}
1179
1180/**
1181 * @qdev_add_legacy_property - adds a legacy property
1182 *
1183 * Do not use this is new code! Properties added through this interface will
1184 * be given types in the "legacy<>" type namespace.
1185 *
1186 * Legacy properties are always processed as strings. The format of the string
1187 * depends on the property type.
1188 */
1189void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1190 Error **errp)
1191{
1192 gchar *type;
1193
1194 type = g_strdup_printf("legacy<%s>", prop->info->name);
1195
1196 qdev_property_add(dev, prop->name, type,
1197 qdev_get_legacy_property,
1198 qdev_set_legacy_property,
1199 NULL,
1200 prop, errp);
1201
1202 g_free(type);
1203}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001204
1205DeviceState *qdev_get_root(void)
1206{
1207 static DeviceState *qdev_root;
1208
1209 if (!qdev_root) {
1210 qdev_root = qdev_create(NULL, "container");
1211 qdev_init_nofail(qdev_root);
1212 }
1213
1214 return qdev_root;
1215}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001216
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001217static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1218 const char *name, Error **errp)
1219{
1220 DeviceState *child = opaque;
1221 gchar *path;
1222
1223 path = qdev_get_canonical_path(child);
1224 visit_type_str(v, &path, name, errp);
1225 g_free(path);
1226}
1227
1228void qdev_property_add_child(DeviceState *dev, const char *name,
1229 DeviceState *child, Error **errp)
1230{
1231 gchar *type;
1232
1233 type = g_strdup_printf("child<%s>", child->info->name);
1234
1235 qdev_property_add(dev, name, type, qdev_get_child_property,
1236 NULL, NULL, child, errp);
1237
1238 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001239 g_assert(child->parent == NULL);
1240 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001241
1242 g_free(type);
1243}
1244
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001245static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1246 const char *name, Error **errp)
1247{
1248 DeviceState **child = opaque;
1249 gchar *path;
1250
1251 if (*child) {
1252 path = qdev_get_canonical_path(*child);
1253 visit_type_str(v, &path, name, errp);
1254 g_free(path);
1255 } else {
1256 path = (gchar *)"";
1257 visit_type_str(v, &path, name, errp);
1258 }
1259}
1260
1261static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1262 const char *name, Error **errp)
1263{
1264 DeviceState **child = opaque;
1265 bool ambiguous = false;
1266 const char *type;
1267 char *path;
1268
1269 type = qdev_property_get_type(dev, name, NULL);
1270
1271 visit_type_str(v, &path, name, errp);
1272
1273 if (*child) {
1274 qdev_unref(*child);
1275 }
1276
1277 if (strcmp(path, "") != 0) {
1278 DeviceState *target;
1279
1280 target = qdev_resolve_path(path, &ambiguous);
1281 if (target) {
1282 gchar *target_type;
1283
1284 target_type = g_strdup_printf("link<%s>", target->info->name);
1285 if (strcmp(target_type, type) == 0) {
1286 *child = target;
1287 qdev_ref(target);
1288 } else {
1289 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1290 }
1291
1292 g_free(target_type);
1293 } else {
1294 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1295 }
1296 } else {
1297 *child = NULL;
1298 }
1299
1300 g_free(path);
1301}
1302
1303void qdev_property_add_link(DeviceState *dev, const char *name,
1304 const char *type, DeviceState **child,
1305 Error **errp)
1306{
1307 gchar *full_type;
1308
1309 full_type = g_strdup_printf("link<%s>", type);
1310
1311 qdev_property_add(dev, name, full_type,
1312 qdev_get_link_property,
1313 qdev_set_link_property,
1314 NULL, child, errp);
1315
1316 g_free(full_type);
1317}
1318
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001319gchar *qdev_get_canonical_path(DeviceState *dev)
1320{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001321 DeviceState *root = qdev_get_root();
1322 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001323
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001324 while (dev != root) {
1325 DeviceProperty *prop = NULL;
1326
1327 g_assert(dev->parent != NULL);
1328
1329 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1330 if (!strstart(prop->type, "child<", NULL)) {
1331 continue;
1332 }
1333
1334 if (prop->opaque == dev) {
1335 if (path) {
1336 newpath = g_strdup_printf("%s/%s", prop->name, path);
1337 g_free(path);
1338 path = newpath;
1339 } else {
1340 path = g_strdup(prop->name);
1341 }
1342 break;
1343 }
1344 }
1345
1346 g_assert(prop != NULL);
1347
1348 dev = dev->parent;
1349 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001350
1351 newpath = g_strdup_printf("/%s", path);
1352 g_free(path);
1353
1354 return newpath;
1355}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001356
1357static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1358 gchar **parts,
1359 int index)
1360{
1361 DeviceProperty *prop;
1362 DeviceState *child;
1363
1364 if (parts[index] == NULL) {
1365 return parent;
1366 }
1367
1368 if (strcmp(parts[index], "") == 0) {
1369 return qdev_resolve_abs_path(parent, parts, index + 1);
1370 }
1371
1372 prop = qdev_property_find(parent, parts[index]);
1373 if (prop == NULL) {
1374 return NULL;
1375 }
1376
1377 child = NULL;
1378 if (strstart(prop->type, "link<", NULL)) {
1379 DeviceState **pchild = prop->opaque;
1380 if (*pchild) {
1381 child = *pchild;
1382 }
1383 } else if (strstart(prop->type, "child<", NULL)) {
1384 child = prop->opaque;
1385 }
1386
1387 if (!child) {
1388 return NULL;
1389 }
1390
1391 return qdev_resolve_abs_path(child, parts, index + 1);
1392}
1393
1394static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1395 gchar **parts,
1396 bool *ambiguous)
1397{
1398 DeviceState *dev;
1399 DeviceProperty *prop;
1400
1401 dev = qdev_resolve_abs_path(parent, parts, 0);
1402
1403 QTAILQ_FOREACH(prop, &parent->properties, node) {
1404 DeviceState *found;
1405
1406 if (!strstart(prop->type, "child<", NULL)) {
1407 continue;
1408 }
1409
1410 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1411 if (found) {
1412 if (dev) {
1413 if (ambiguous) {
1414 *ambiguous = true;
1415 }
1416 return NULL;
1417 }
1418 dev = found;
1419 }
1420
1421 if (ambiguous && *ambiguous) {
1422 return NULL;
1423 }
1424 }
1425
1426 return dev;
1427}
1428
1429DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1430{
1431 bool partial_path = true;
1432 DeviceState *dev;
1433 gchar **parts;
1434
1435 parts = g_strsplit(path, "/", 0);
1436 if (parts == NULL || parts[0] == NULL) {
1437 g_strfreev(parts);
1438 return qdev_get_root();
1439 }
1440
1441 if (strcmp(parts[0], "") == 0) {
1442 partial_path = false;
1443 }
1444
1445 if (partial_path) {
1446 if (ambiguous) {
1447 *ambiguous = false;
1448 }
1449 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1450 } else {
1451 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1452 }
1453
1454 g_strfreev(parts);
1455
1456 return dev;
1457}
1458
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001459typedef struct StringProperty
1460{
1461 char *(*get)(DeviceState *, Error **);
1462 void (*set)(DeviceState *, const char *, Error **);
1463} StringProperty;
1464
1465static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1466 const char *name, Error **errp)
1467{
1468 StringProperty *prop = opaque;
1469 char *value;
1470
1471 value = prop->get(dev, errp);
1472 if (value) {
1473 visit_type_str(v, &value, name, errp);
1474 g_free(value);
1475 }
1476}
1477
1478static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1479 const char *name, Error **errp)
1480{
1481 StringProperty *prop = opaque;
1482 char *value;
1483 Error *local_err = NULL;
1484
1485 visit_type_str(v, &value, name, &local_err);
1486 if (local_err) {
1487 error_propagate(errp, local_err);
1488 return;
1489 }
1490
1491 prop->set(dev, value, errp);
1492 g_free(value);
1493}
1494
1495static void qdev_property_release_str(DeviceState *dev, const char *name,
1496 void *opaque)
1497{
1498 StringProperty *prop = opaque;
1499 g_free(prop);
1500}
1501
1502void qdev_property_add_str(DeviceState *dev, const char *name,
1503 char *(*get)(DeviceState *, Error **),
1504 void (*set)(DeviceState *, const char *, Error **),
1505 Error **errp)
1506{
1507 StringProperty *prop = g_malloc0(sizeof(*prop));
1508
1509 prop->get = get;
1510 prop->set = set;
1511
1512 qdev_property_add(dev, name, "string",
1513 get ? qdev_property_get_str : NULL,
1514 set ? qdev_property_set_str : NULL,
1515 qdev_property_release_str,
1516 prop, errp);
1517}