blob: fdc984312c4584e4819e9866897aca415fb45801 [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;
86
Markus Armbruster0c175422010-02-19 19:12:18 +010087 assert(bus->info == info->bus_info);
Anthony Liguori7267c092011-08-20 22:09:37 -050088 dev = g_malloc0(info->size);
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020089 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +010090 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020091 qdev_prop_set_defaults(dev, dev->info->props);
92 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010093 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +020094 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020095 if (qdev_hotplug) {
96 assert(bus->allow_hotplug);
97 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070098 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020099 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200100 dev->instance_id_alias = -1;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200101 dev->state = DEV_STATE_CREATED;
Paul Brookaae94602009-05-14 22:35:06 +0100102 return dev;
103}
104
Markus Armbruster0c175422010-02-19 19:12:18 +0100105/* Create a new device. This only initializes the device state structure
106 and allows properties to be set. qdev_init should be called to
107 initialize the actual device emulation. */
108DeviceState *qdev_create(BusState *bus, const char *name)
109{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000110 DeviceState *dev;
111
112 dev = qdev_try_create(bus, name);
113 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100114 if (bus) {
115 hw_error("Unknown device '%s' for bus '%s'\n", name,
116 bus->info->name);
117 } else {
118 hw_error("Unknown device '%s' for default sysbus\n", name);
119 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000120 }
121
122 return dev;
123}
124
125DeviceState *qdev_try_create(BusState *bus, const char *name)
126{
Markus Armbruster0c175422010-02-19 19:12:18 +0100127 DeviceInfo *info;
128
129 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100130 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100131 }
132
133 info = qdev_find_info(bus->info, name);
134 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000135 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100136 }
137
138 return qdev_create_from_info(bus, info);
139}
140
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100141static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200142{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100143 error_printf("name \"%s\", bus %s",
144 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200145 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100146 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200147 }
148 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100149 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200150 }
151 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100152 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200153 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100154 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200155}
156
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200157static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200158{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200159 DeviceState *dev = opaque;
160
161 if (strcmp(name, "driver") == 0)
162 return 0;
163 if (strcmp(name, "bus") == 0)
164 return 0;
165
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100166 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200167 return -1;
168 }
169 return 0;
170}
171
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100172int qdev_device_help(QemuOpts *opts)
173{
174 const char *driver;
175 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100176 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100177
178 driver = qemu_opt_get(opts, "driver");
179 if (driver && !strcmp(driver, "?")) {
180 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100181 if (info->no_user) {
182 continue; /* not available, don't show */
183 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100184 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100185 }
186 return 1;
187 }
188
Markus Armbruster542379f2011-11-08 11:00:38 +0100189 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100190 return 0;
191 }
192
193 info = qdev_find_info(NULL, driver);
194 if (!info) {
195 return 0;
196 }
197
198 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100199 /*
200 * TODO Properties without a parser are just for dirty hacks.
201 * qdev_prop_ptr is the only such PropertyInfo. It's marked
202 * for removal. This conditional should be removed along with
203 * it.
204 */
205 if (!prop->info->parse) {
206 continue; /* no way to set it, don't show */
207 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100208 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100209 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200210 for (prop = info->bus_info->props; prop && prop->name; prop++) {
211 if (!prop->info->parse) {
212 continue; /* no way to set it, don't show */
213 }
214 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
215 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100216 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100217}
218
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200219DeviceState *qdev_device_add(QemuOpts *opts)
220{
221 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200222 DeviceInfo *info;
223 DeviceState *qdev;
224 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200225
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200226 driver = qemu_opt_get(opts, "driver");
227 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100228 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200229 return NULL;
230 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200231
232 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200233 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100234 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100235 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100236 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200237 return NULL;
238 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200239
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200240 /* find bus */
241 path = qemu_opt_get(opts, "bus");
242 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200243 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100244 if (!bus) {
245 return NULL;
246 }
247 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100248 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
249 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100250 return NULL;
251 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200252 } else {
253 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100254 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100255 qerror_report(QERR_NO_BUS_FOR_DEVICE,
256 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100257 return NULL;
258 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200259 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200260 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100261 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200262 return NULL;
263 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200264
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200265 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100266 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200267 id = qemu_opts_id(opts);
268 if (id) {
269 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200270 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200271 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
272 qdev_free(qdev);
273 return NULL;
274 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200275 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100276 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200277 return NULL;
278 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200279 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200280 return qdev;
281}
282
Paul Brookaae94602009-05-14 22:35:06 +0100283/* Initialize a device. Device properties should be set before calling
284 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200285 calling this function.
286 On failure, destroy the device and return negative value.
287 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200288int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100289{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200290 int rc;
291
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200292 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200293 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200294 if (rc < 0) {
295 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200296 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200297 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200298 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600299 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200300 dev->instance_id_alias,
301 dev->alias_required_for_version);
302 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200303 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200304 if (dev->hotplugged && dev->info->reset) {
305 dev->info->reset(dev);
306 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200307 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100308}
309
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200310void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
311 int required_for_version)
312{
313 assert(dev->state == DEV_STATE_CREATED);
314 dev->instance_id_alias = alias_id;
315 dev->alias_required_for_version = required_for_version;
316}
317
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200318int qdev_unplug(DeviceState *dev)
319{
320 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100321 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200322 return -1;
323 }
Amit Shah593831d2009-11-02 14:56:41 +0530324 assert(dev->info->unplug != NULL);
325
Anthony Liguori85ed3032011-12-12 14:29:25 -0600326 if (dev->ref != 0) {
327 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
328 return -1;
329 }
330
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700331 qdev_hot_removed = true;
332
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200333 return dev->info->unplug(dev);
334}
335
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900336static int qdev_reset_one(DeviceState *dev, void *opaque)
337{
338 if (dev->info->reset) {
339 dev->info->reset(dev);
340 }
341
342 return 0;
343}
344
345BusState *sysbus_get_default(void)
346{
Stefan Weil68694892010-12-16 19:33:22 +0100347 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900348 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100349 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900350 return main_system_bus;
351}
352
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900353static int qbus_reset_one(BusState *bus, void *opaque)
354{
355 if (bus->info->reset) {
356 return bus->info->reset(bus);
357 }
358 return 0;
359}
360
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900361void qdev_reset_all(DeviceState *dev)
362{
363 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
364}
365
Isaku Yamahata80376c32010-12-20 14:33:35 +0900366void qbus_reset_all_fn(void *opaque)
367{
368 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200369 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900370}
371
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200372/* can be used as ->unplug() callback for the simple cases */
373int qdev_simple_unplug_cb(DeviceState *dev)
374{
375 /* just zap it */
376 qdev_free(dev);
377 return 0;
378}
379
Michael Tokarev3b29a102011-04-06 17:51:59 +0400380
381/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200382 returning an error value. This is okay during machine creation.
383 Don't use for hotplug, because there callers need to recover from
384 failure. Exception: if you know the device's init() callback can't
385 fail, then qdev_init_nofail() can't fail either, and is therefore
386 usable even then. But relying on the device implementation that
387 way is somewhat unclean, and best avoided. */
388void qdev_init_nofail(DeviceState *dev)
389{
390 DeviceInfo *info = dev->info;
391
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200392 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200393 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200394 exit(1);
395 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200396}
397
Paul Brook02e2da42009-05-23 00:05:19 +0100398/* Unlink device from bus and free the structure. */
399void qdev_free(DeviceState *dev)
400{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200401 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200402 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200403
404 if (dev->state == DEV_STATE_INITIALIZED) {
405 while (dev->num_child_bus) {
406 bus = QLIST_FIRST(&dev->child_bus);
407 qbus_free(bus);
408 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200409 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600410 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200411 if (dev->info->exit)
412 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200413 if (dev->opts)
414 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200415 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200416 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200417 for (prop = dev->info->props; prop && prop->name; prop++) {
418 if (prop->info->free) {
419 prop->info->free(dev, prop);
420 }
421 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500422 g_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100423}
424
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200425void qdev_machine_creation_done(void)
426{
427 /*
428 * ok, initial machine setup is done, starting from now we can
429 * only create hotpluggable devices
430 */
431 qdev_hotplug = 1;
432}
433
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700434bool qdev_machine_modified(void)
435{
436 return qdev_hot_added || qdev_hot_removed;
437}
438
Paul Brookaae94602009-05-14 22:35:06 +0100439/* Get a character (serial) device interface. */
440CharDriverState *qdev_init_chardev(DeviceState *dev)
441{
442 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530443
444 /* FIXME: This function needs to go away: use chardev properties! */
445 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100446}
447
Paul Brook02e2da42009-05-23 00:05:19 +0100448BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100449{
Paul Brook02e2da42009-05-23 00:05:19 +0100450 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100451}
452
Paul Brookaae94602009-05-14 22:35:06 +0100453void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
454{
455 assert(dev->num_gpio_in == 0);
456 dev->num_gpio_in = n;
457 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
458}
459
460void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
461{
462 assert(dev->num_gpio_out == 0);
463 dev->num_gpio_out = n;
464 dev->gpio_out = pins;
465}
466
467qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
468{
469 assert(n >= 0 && n < dev->num_gpio_in);
470 return dev->gpio_in[n];
471}
472
473void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
474{
475 assert(n >= 0 && n < dev->num_gpio_out);
476 dev->gpio_out[n] = pin;
477}
478
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200479void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
480{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200481 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200482 if (nd->vlan)
483 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
484 if (nd->netdev)
485 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530486 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200487 qdev_prop_exists(dev, "vectors")) {
488 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
489 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100490 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200491}
492
Paul Brook02e2da42009-05-23 00:05:19 +0100493BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100494{
Paul Brook02e2da42009-05-23 00:05:19 +0100495 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100496
Blue Swirl72cf2d42009-09-12 07:36:22 +0000497 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100498 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100499 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100500 }
501 }
502 return NULL;
503}
504
Anthony Liguori81699d82010-11-19 18:55:58 +0900505int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
506 qbus_walkerfn *busfn, void *opaque)
507{
508 DeviceState *dev;
509 int err;
510
511 if (busfn) {
512 err = busfn(bus, opaque);
513 if (err) {
514 return err;
515 }
516 }
517
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200518 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900519 err = qdev_walk_children(dev, devfn, busfn, opaque);
520 if (err < 0) {
521 return err;
522 }
523 }
524
525 return 0;
526}
527
528int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
529 qbus_walkerfn *busfn, void *opaque)
530{
531 BusState *bus;
532 int err;
533
534 if (devfn) {
535 err = devfn(dev, opaque);
536 if (err) {
537 return err;
538 }
539 }
540
541 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
542 err = qbus_walk_children(bus, devfn, busfn, opaque);
543 if (err < 0) {
544 return err;
545 }
546 }
547
548 return 0;
549}
550
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200551static BusState *qbus_find_recursive(BusState *bus, const char *name,
552 const BusInfo *info)
553{
554 DeviceState *dev;
555 BusState *child, *ret;
556 int match = 1;
557
558 if (name && (strcmp(bus->name, name) != 0)) {
559 match = 0;
560 }
561 if (info && (bus->info != info)) {
562 match = 0;
563 }
564 if (match) {
565 return bus;
566 }
567
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200568 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000569 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200570 ret = qbus_find_recursive(child, name, info);
571 if (ret) {
572 return ret;
573 }
574 }
575 }
576 return NULL;
577}
578
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900579DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200580{
581 DeviceState *dev, *ret;
582 BusState *child;
583
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200584 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200585 if (dev->id && strcmp(dev->id, id) == 0)
586 return dev;
587 QLIST_FOREACH(child, &dev->child_bus, sibling) {
588 ret = qdev_find_recursive(child, id);
589 if (ret) {
590 return ret;
591 }
592 }
593 }
594 return NULL;
595}
596
Markus Armbruster53db16b2010-02-18 18:55:59 +0100597static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200598{
599 BusState *child;
600 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200601
Markus Armbruster53db16b2010-02-18 18:55:59 +0100602 error_printf("child busses at \"%s\":",
603 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000604 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100605 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200606 sep = ", ";
607 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100608 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200609}
610
Markus Armbruster53db16b2010-02-18 18:55:59 +0100611static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200612{
613 DeviceState *dev;
614 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200615
Markus Armbruster53db16b2010-02-18 18:55:59 +0100616 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200617 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100618 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200619 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100620 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200621 sep = ", ";
622 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100623 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200624}
625
626static BusState *qbus_find_bus(DeviceState *dev, char *elem)
627{
628 BusState *child;
629
Blue Swirl72cf2d42009-09-12 07:36:22 +0000630 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200631 if (strcmp(child->name, elem) == 0) {
632 return child;
633 }
634 }
635 return NULL;
636}
637
638static DeviceState *qbus_find_dev(BusState *bus, char *elem)
639{
640 DeviceState *dev;
641
642 /*
643 * try to match in order:
644 * (1) instance id, if present
645 * (2) driver name
646 * (3) driver alias, if present
647 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200648 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200649 if (dev->id && strcmp(dev->id, elem) == 0) {
650 return dev;
651 }
652 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200653 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200654 if (strcmp(dev->info->name, elem) == 0) {
655 return dev;
656 }
657 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200658 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200659 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
660 return dev;
661 }
662 }
663 return NULL;
664}
665
666static BusState *qbus_find(const char *path)
667{
668 DeviceState *dev;
669 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100670 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200671 int pos, len;
672
673 /* find start element */
674 if (path[0] == '/') {
675 bus = main_system_bus;
676 pos = 0;
677 } else {
678 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100679 assert(!path[0]);
680 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200681 }
682 bus = qbus_find_recursive(main_system_bus, elem, NULL);
683 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100684 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200685 return NULL;
686 }
687 pos = len;
688 }
689
690 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100691 assert(path[pos] == '/' || !path[pos]);
692 while (path[pos] == '/') {
693 pos++;
694 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200695 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200696 return bus;
697 }
698
699 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100700 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
701 assert(0);
702 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200703 }
704 pos += len;
705 dev = qbus_find_dev(bus, elem);
706 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100707 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100708 if (!monitor_cur_is_qmp()) {
709 qbus_list_dev(bus);
710 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200711 return NULL;
712 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100713
714 assert(path[pos] == '/' || !path[pos]);
715 while (path[pos] == '/') {
716 pos++;
717 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200718 if (path[pos] == '\0') {
719 /* last specified element is a device. If it has exactly
720 * one child bus accept it nevertheless */
721 switch (dev->num_child_bus) {
722 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100723 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200724 return NULL;
725 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000726 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200727 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100728 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100729 if (!monitor_cur_is_qmp()) {
730 qbus_list_bus(dev);
731 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200732 return NULL;
733 }
734 }
735
736 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100737 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
738 assert(0);
739 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200740 }
741 pos += len;
742 bus = qbus_find_bus(dev, elem);
743 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100744 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100745 if (!monitor_cur_is_qmp()) {
746 qbus_list_bus(dev);
747 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200748 return NULL;
749 }
750 }
751}
752
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200753void qbus_create_inplace(BusState *bus, BusInfo *info,
754 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100755{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200756 char *buf;
757 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100758
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200759 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100760 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200761
762 if (name) {
763 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500764 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200765 } else if (parent && parent->id) {
766 /* parent device has id -> use it for bus name */
767 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500768 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200769 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
770 bus->name = buf;
771 } else {
772 /* no id -> use lowercase bus type for bus name */
773 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500774 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200775 len = snprintf(buf, len, "%s.%d", info->name,
776 parent ? parent->num_child_bus : 0);
777 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200778 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200779 bus->name = buf;
780 }
781
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200782 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100783 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000784 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200785 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900786 } else if (bus != main_system_bus) {
787 /* TODO: once all bus devices are qdevified,
788 only reset handler for main_system_bus should be registered here. */
789 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100790 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200791}
792
793BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
794{
795 BusState *bus;
796
Anthony Liguori7267c092011-08-20 22:09:37 -0500797 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200798 bus->qdev_allocated = 1;
799 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100800 return bus;
801}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100802
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900803static void main_system_bus_create(void)
804{
805 /* assign main_system_bus before qbus_create_inplace()
806 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500807 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900808 main_system_bus->qdev_allocated = 1;
809 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
810 "main-system-bus");
811}
812
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200813void qbus_free(BusState *bus)
814{
815 DeviceState *dev;
816
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200817 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200818 qdev_free(dev);
819 }
820 if (bus->parent) {
821 QLIST_REMOVE(bus, sibling);
822 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900823 } else {
824 assert(bus != main_system_bus); /* main_system_bus is never freed */
825 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200826 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500827 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200828 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500829 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200830 }
831}
832
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100833#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
834static void qbus_print(Monitor *mon, BusState *bus, int indent);
835
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200836static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
837 const char *prefix, int indent)
838{
839 char buf[64];
840
841 if (!props)
842 return;
843 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100844 /*
845 * TODO Properties without a print method are just for dirty
846 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
847 * marked for removal. The test props->info->print should be
848 * removed along with it.
849 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200850 if (props->info->print) {
851 props->info->print(dev, props, buf, sizeof(buf));
852 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
853 }
854 props++;
855 }
856}
857
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100858static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
859{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100860 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200861 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
862 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100863 indent += 2;
864 if (dev->num_gpio_in) {
865 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
866 }
867 if (dev->num_gpio_out) {
868 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
869 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200870 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
871 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200872 if (dev->parent_bus->info->print_dev)
873 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000874 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100875 qbus_print(mon, child, indent);
876 }
877}
878
879static void qbus_print(Monitor *mon, BusState *bus, int indent)
880{
881 struct DeviceState *dev;
882
883 qdev_printf("bus: %s\n", bus->name);
884 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200885 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200886 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100887 qdev_print(mon, dev, indent);
888 }
889}
890#undef qdev_printf
891
892void do_info_qtree(Monitor *mon)
893{
894 if (main_system_bus)
895 qbus_print(mon, main_system_bus, 0);
896}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200897
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200898void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200899{
900 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200901
902 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100903 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200904 }
905}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200906
Markus Armbruster8bc27242010-02-10 20:52:01 +0100907int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200908{
909 QemuOpts *opts;
910
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200911 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100912 if (!opts) {
913 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100914 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100915 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
916 qemu_opts_del(opts);
917 return 0;
918 }
919 if (!qdev_device_add(opts)) {
920 qemu_opts_del(opts);
921 return -1;
922 }
923 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200924}
925
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100926int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200927{
928 const char *id = qdict_get_str(qdict, "id");
929 DeviceState *dev;
930
931 dev = qdev_find_recursive(main_system_bus, id);
932 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100933 qerror_report(QERR_DEVICE_NOT_FOUND, id);
934 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200935 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100936 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200937}
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200938
939static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
940{
941 int l = 0;
942
943 if (dev && dev->parent_bus) {
944 char *d;
945 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
946 if (dev->parent_bus->info->get_fw_dev_path) {
947 d = dev->parent_bus->info->get_fw_dev_path(dev);
948 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500949 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200950 } else {
951 l += snprintf(p + l, size - l, "%s", dev->info->name);
952 }
953 }
954 l += snprintf(p + l , size - l, "/");
955
956 return l;
957}
958
959char* qdev_get_fw_dev_path(DeviceState *dev)
960{
961 char path[128];
962 int l;
963
964 l = qdev_get_fw_dev_path_helper(dev, path, 128);
965
966 path[l-1] = '\0';
967
968 return strdup(path);
969}
Anthony Liguori85ed3032011-12-12 14:29:25 -0600970
971void qdev_ref(DeviceState *dev)
972{
973 dev->ref++;
974}
975
976void qdev_unref(DeviceState *dev)
977{
978 g_assert(dev->ref > 0);
979 dev->ref--;
980}