blob: 94f14c1f1cd255ced971a2b53db9f3c08a1bcef9 [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;
Anthony Liguori44677de2011-12-12 14:29:26 -0600101 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200102 dev->state = DEV_STATE_CREATED;
Paul Brookaae94602009-05-14 22:35:06 +0100103 return dev;
104}
105
Markus Armbruster0c175422010-02-19 19:12:18 +0100106/* Create a new device. This only initializes the device state structure
107 and allows properties to be set. qdev_init should be called to
108 initialize the actual device emulation. */
109DeviceState *qdev_create(BusState *bus, const char *name)
110{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000111 DeviceState *dev;
112
113 dev = qdev_try_create(bus, name);
114 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100115 if (bus) {
116 hw_error("Unknown device '%s' for bus '%s'\n", name,
117 bus->info->name);
118 } else {
119 hw_error("Unknown device '%s' for default sysbus\n", name);
120 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000121 }
122
123 return dev;
124}
125
126DeviceState *qdev_try_create(BusState *bus, const char *name)
127{
Markus Armbruster0c175422010-02-19 19:12:18 +0100128 DeviceInfo *info;
129
130 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100131 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100132 }
133
134 info = qdev_find_info(bus->info, name);
135 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000136 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100137 }
138
139 return qdev_create_from_info(bus, info);
140}
141
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100142static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200143{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100144 error_printf("name \"%s\", bus %s",
145 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200146 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100147 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200148 }
149 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100150 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200151 }
152 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100153 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200154 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100155 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200156}
157
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200158static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200159{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200160 DeviceState *dev = opaque;
161
162 if (strcmp(name, "driver") == 0)
163 return 0;
164 if (strcmp(name, "bus") == 0)
165 return 0;
166
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100167 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200168 return -1;
169 }
170 return 0;
171}
172
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100173int qdev_device_help(QemuOpts *opts)
174{
175 const char *driver;
176 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100177 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100178
179 driver = qemu_opt_get(opts, "driver");
180 if (driver && !strcmp(driver, "?")) {
181 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100182 if (info->no_user) {
183 continue; /* not available, don't show */
184 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100185 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100186 }
187 return 1;
188 }
189
Markus Armbruster542379f2011-11-08 11:00:38 +0100190 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100191 return 0;
192 }
193
194 info = qdev_find_info(NULL, driver);
195 if (!info) {
196 return 0;
197 }
198
199 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100200 /*
201 * TODO Properties without a parser are just for dirty hacks.
202 * qdev_prop_ptr is the only such PropertyInfo. It's marked
203 * for removal. This conditional should be removed along with
204 * it.
205 */
206 if (!prop->info->parse) {
207 continue; /* no way to set it, don't show */
208 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100209 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100210 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200211 for (prop = info->bus_info->props; prop && prop->name; prop++) {
212 if (!prop->info->parse) {
213 continue; /* no way to set it, don't show */
214 }
215 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
216 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100217 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100218}
219
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200220DeviceState *qdev_device_add(QemuOpts *opts)
221{
222 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200223 DeviceInfo *info;
224 DeviceState *qdev;
225 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200226
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200227 driver = qemu_opt_get(opts, "driver");
228 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100229 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200230 return NULL;
231 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200232
233 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200234 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100235 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100236 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100237 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200238 return NULL;
239 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200240
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200241 /* find bus */
242 path = qemu_opt_get(opts, "bus");
243 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200244 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100245 if (!bus) {
246 return NULL;
247 }
248 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100249 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
250 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100251 return NULL;
252 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200253 } else {
254 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100255 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100256 qerror_report(QERR_NO_BUS_FOR_DEVICE,
257 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100258 return NULL;
259 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200260 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200261 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100262 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200263 return NULL;
264 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200265
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200266 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100267 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200268 id = qemu_opts_id(opts);
269 if (id) {
270 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200271 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200272 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
273 qdev_free(qdev);
274 return NULL;
275 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200276 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100277 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200278 return NULL;
279 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200280 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200281 return qdev;
282}
283
Paul Brookaae94602009-05-14 22:35:06 +0100284/* Initialize a device. Device properties should be set before calling
285 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200286 calling this function.
287 On failure, destroy the device and return negative value.
288 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200289int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100290{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200291 int rc;
292
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200293 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200294 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200295 if (rc < 0) {
296 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200297 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200298 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200299 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600300 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200301 dev->instance_id_alias,
302 dev->alias_required_for_version);
303 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200304 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200305 if (dev->hotplugged && dev->info->reset) {
306 dev->info->reset(dev);
307 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200308 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100309}
310
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200311void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
312 int required_for_version)
313{
314 assert(dev->state == DEV_STATE_CREATED);
315 dev->instance_id_alias = alias_id;
316 dev->alias_required_for_version = required_for_version;
317}
318
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200319int qdev_unplug(DeviceState *dev)
320{
321 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100322 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200323 return -1;
324 }
Amit Shah593831d2009-11-02 14:56:41 +0530325 assert(dev->info->unplug != NULL);
326
Anthony Liguori85ed3032011-12-12 14:29:25 -0600327 if (dev->ref != 0) {
328 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
329 return -1;
330 }
331
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700332 qdev_hot_removed = true;
333
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200334 return dev->info->unplug(dev);
335}
336
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900337static int qdev_reset_one(DeviceState *dev, void *opaque)
338{
339 if (dev->info->reset) {
340 dev->info->reset(dev);
341 }
342
343 return 0;
344}
345
346BusState *sysbus_get_default(void)
347{
Stefan Weil68694892010-12-16 19:33:22 +0100348 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900349 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100350 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900351 return main_system_bus;
352}
353
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900354static int qbus_reset_one(BusState *bus, void *opaque)
355{
356 if (bus->info->reset) {
357 return bus->info->reset(bus);
358 }
359 return 0;
360}
361
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900362void qdev_reset_all(DeviceState *dev)
363{
364 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
365}
366
Isaku Yamahata80376c32010-12-20 14:33:35 +0900367void qbus_reset_all_fn(void *opaque)
368{
369 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200370 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900371}
372
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200373/* can be used as ->unplug() callback for the simple cases */
374int qdev_simple_unplug_cb(DeviceState *dev)
375{
376 /* just zap it */
377 qdev_free(dev);
378 return 0;
379}
380
Michael Tokarev3b29a102011-04-06 17:51:59 +0400381
382/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200383 returning an error value. This is okay during machine creation.
384 Don't use for hotplug, because there callers need to recover from
385 failure. Exception: if you know the device's init() callback can't
386 fail, then qdev_init_nofail() can't fail either, and is therefore
387 usable even then. But relying on the device implementation that
388 way is somewhat unclean, and best avoided. */
389void qdev_init_nofail(DeviceState *dev)
390{
391 DeviceInfo *info = dev->info;
392
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200393 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200394 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200395 exit(1);
396 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200397}
398
Anthony Liguori44677de2011-12-12 14:29:26 -0600399static void qdev_property_del_all(DeviceState *dev)
400{
401 while (!QTAILQ_EMPTY(&dev->properties)) {
402 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
403
404 QTAILQ_REMOVE(&dev->properties, prop, node);
405
406 if (prop->release) {
407 prop->release(dev, prop->name, prop->opaque);
408 }
409
410 g_free(prop->name);
411 g_free(prop->type);
412 g_free(prop);
413 }
414}
415
Paul Brook02e2da42009-05-23 00:05:19 +0100416/* Unlink device from bus and free the structure. */
417void qdev_free(DeviceState *dev)
418{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200419 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200420 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200421
Anthony Liguori44677de2011-12-12 14:29:26 -0600422 qdev_property_del_all(dev);
423
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200424 if (dev->state == DEV_STATE_INITIALIZED) {
425 while (dev->num_child_bus) {
426 bus = QLIST_FIRST(&dev->child_bus);
427 qbus_free(bus);
428 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200429 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600430 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200431 if (dev->info->exit)
432 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200433 if (dev->opts)
434 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200435 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200436 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200437 for (prop = dev->info->props; prop && prop->name; prop++) {
438 if (prop->info->free) {
439 prop->info->free(dev, prop);
440 }
441 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500442 g_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100443}
444
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200445void qdev_machine_creation_done(void)
446{
447 /*
448 * ok, initial machine setup is done, starting from now we can
449 * only create hotpluggable devices
450 */
451 qdev_hotplug = 1;
452}
453
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700454bool qdev_machine_modified(void)
455{
456 return qdev_hot_added || qdev_hot_removed;
457}
458
Paul Brookaae94602009-05-14 22:35:06 +0100459/* Get a character (serial) device interface. */
460CharDriverState *qdev_init_chardev(DeviceState *dev)
461{
462 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530463
464 /* FIXME: This function needs to go away: use chardev properties! */
465 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100466}
467
Paul Brook02e2da42009-05-23 00:05:19 +0100468BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100469{
Paul Brook02e2da42009-05-23 00:05:19 +0100470 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100471}
472
Paul Brookaae94602009-05-14 22:35:06 +0100473void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
474{
475 assert(dev->num_gpio_in == 0);
476 dev->num_gpio_in = n;
477 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
478}
479
480void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
481{
482 assert(dev->num_gpio_out == 0);
483 dev->num_gpio_out = n;
484 dev->gpio_out = pins;
485}
486
487qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
488{
489 assert(n >= 0 && n < dev->num_gpio_in);
490 return dev->gpio_in[n];
491}
492
493void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
494{
495 assert(n >= 0 && n < dev->num_gpio_out);
496 dev->gpio_out[n] = pin;
497}
498
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200499void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
500{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200501 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200502 if (nd->vlan)
503 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
504 if (nd->netdev)
505 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530506 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200507 qdev_prop_exists(dev, "vectors")) {
508 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
509 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100510 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200511}
512
Paul Brook02e2da42009-05-23 00:05:19 +0100513BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100514{
Paul Brook02e2da42009-05-23 00:05:19 +0100515 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100516
Blue Swirl72cf2d42009-09-12 07:36:22 +0000517 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100518 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100519 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100520 }
521 }
522 return NULL;
523}
524
Anthony Liguori81699d82010-11-19 18:55:58 +0900525int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
526 qbus_walkerfn *busfn, void *opaque)
527{
528 DeviceState *dev;
529 int err;
530
531 if (busfn) {
532 err = busfn(bus, opaque);
533 if (err) {
534 return err;
535 }
536 }
537
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200538 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900539 err = qdev_walk_children(dev, devfn, busfn, opaque);
540 if (err < 0) {
541 return err;
542 }
543 }
544
545 return 0;
546}
547
548int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
549 qbus_walkerfn *busfn, void *opaque)
550{
551 BusState *bus;
552 int err;
553
554 if (devfn) {
555 err = devfn(dev, opaque);
556 if (err) {
557 return err;
558 }
559 }
560
561 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
562 err = qbus_walk_children(bus, devfn, busfn, opaque);
563 if (err < 0) {
564 return err;
565 }
566 }
567
568 return 0;
569}
570
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200571static BusState *qbus_find_recursive(BusState *bus, const char *name,
572 const BusInfo *info)
573{
574 DeviceState *dev;
575 BusState *child, *ret;
576 int match = 1;
577
578 if (name && (strcmp(bus->name, name) != 0)) {
579 match = 0;
580 }
581 if (info && (bus->info != info)) {
582 match = 0;
583 }
584 if (match) {
585 return bus;
586 }
587
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200588 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000589 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200590 ret = qbus_find_recursive(child, name, info);
591 if (ret) {
592 return ret;
593 }
594 }
595 }
596 return NULL;
597}
598
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900599DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200600{
601 DeviceState *dev, *ret;
602 BusState *child;
603
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200604 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200605 if (dev->id && strcmp(dev->id, id) == 0)
606 return dev;
607 QLIST_FOREACH(child, &dev->child_bus, sibling) {
608 ret = qdev_find_recursive(child, id);
609 if (ret) {
610 return ret;
611 }
612 }
613 }
614 return NULL;
615}
616
Markus Armbruster53db16b2010-02-18 18:55:59 +0100617static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200618{
619 BusState *child;
620 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200621
Markus Armbruster53db16b2010-02-18 18:55:59 +0100622 error_printf("child busses at \"%s\":",
623 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000624 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100625 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200626 sep = ", ";
627 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100628 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200629}
630
Markus Armbruster53db16b2010-02-18 18:55:59 +0100631static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200632{
633 DeviceState *dev;
634 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200635
Markus Armbruster53db16b2010-02-18 18:55:59 +0100636 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200637 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100638 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200639 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100640 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200641 sep = ", ";
642 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100643 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200644}
645
646static BusState *qbus_find_bus(DeviceState *dev, char *elem)
647{
648 BusState *child;
649
Blue Swirl72cf2d42009-09-12 07:36:22 +0000650 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200651 if (strcmp(child->name, elem) == 0) {
652 return child;
653 }
654 }
655 return NULL;
656}
657
658static DeviceState *qbus_find_dev(BusState *bus, char *elem)
659{
660 DeviceState *dev;
661
662 /*
663 * try to match in order:
664 * (1) instance id, if present
665 * (2) driver name
666 * (3) driver alias, if present
667 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200668 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200669 if (dev->id && strcmp(dev->id, elem) == 0) {
670 return dev;
671 }
672 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200673 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200674 if (strcmp(dev->info->name, elem) == 0) {
675 return dev;
676 }
677 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200678 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200679 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
680 return dev;
681 }
682 }
683 return NULL;
684}
685
686static BusState *qbus_find(const char *path)
687{
688 DeviceState *dev;
689 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100690 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200691 int pos, len;
692
693 /* find start element */
694 if (path[0] == '/') {
695 bus = main_system_bus;
696 pos = 0;
697 } else {
698 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100699 assert(!path[0]);
700 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200701 }
702 bus = qbus_find_recursive(main_system_bus, elem, NULL);
703 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100704 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200705 return NULL;
706 }
707 pos = len;
708 }
709
710 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100711 assert(path[pos] == '/' || !path[pos]);
712 while (path[pos] == '/') {
713 pos++;
714 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200715 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200716 return bus;
717 }
718
719 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100720 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
721 assert(0);
722 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200723 }
724 pos += len;
725 dev = qbus_find_dev(bus, elem);
726 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100727 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100728 if (!monitor_cur_is_qmp()) {
729 qbus_list_dev(bus);
730 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200731 return NULL;
732 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100733
734 assert(path[pos] == '/' || !path[pos]);
735 while (path[pos] == '/') {
736 pos++;
737 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200738 if (path[pos] == '\0') {
739 /* last specified element is a device. If it has exactly
740 * one child bus accept it nevertheless */
741 switch (dev->num_child_bus) {
742 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100743 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200744 return NULL;
745 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000746 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200747 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100748 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100749 if (!monitor_cur_is_qmp()) {
750 qbus_list_bus(dev);
751 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200752 return NULL;
753 }
754 }
755
756 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100757 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
758 assert(0);
759 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200760 }
761 pos += len;
762 bus = qbus_find_bus(dev, elem);
763 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100764 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100765 if (!monitor_cur_is_qmp()) {
766 qbus_list_bus(dev);
767 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200768 return NULL;
769 }
770 }
771}
772
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200773void qbus_create_inplace(BusState *bus, BusInfo *info,
774 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100775{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200776 char *buf;
777 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100778
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200779 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100780 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200781
782 if (name) {
783 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500784 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200785 } else if (parent && parent->id) {
786 /* parent device has id -> use it for bus name */
787 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500788 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200789 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
790 bus->name = buf;
791 } else {
792 /* no id -> use lowercase bus type for bus name */
793 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500794 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200795 len = snprintf(buf, len, "%s.%d", info->name,
796 parent ? parent->num_child_bus : 0);
797 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200798 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200799 bus->name = buf;
800 }
801
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200802 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100803 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000804 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200805 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900806 } else if (bus != main_system_bus) {
807 /* TODO: once all bus devices are qdevified,
808 only reset handler for main_system_bus should be registered here. */
809 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100810 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200811}
812
813BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
814{
815 BusState *bus;
816
Anthony Liguori7267c092011-08-20 22:09:37 -0500817 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200818 bus->qdev_allocated = 1;
819 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100820 return bus;
821}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100822
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900823static void main_system_bus_create(void)
824{
825 /* assign main_system_bus before qbus_create_inplace()
826 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500827 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900828 main_system_bus->qdev_allocated = 1;
829 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
830 "main-system-bus");
831}
832
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200833void qbus_free(BusState *bus)
834{
835 DeviceState *dev;
836
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200837 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200838 qdev_free(dev);
839 }
840 if (bus->parent) {
841 QLIST_REMOVE(bus, sibling);
842 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900843 } else {
844 assert(bus != main_system_bus); /* main_system_bus is never freed */
845 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200846 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500847 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200848 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500849 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200850 }
851}
852
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100853#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
854static void qbus_print(Monitor *mon, BusState *bus, int indent);
855
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200856static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
857 const char *prefix, int indent)
858{
859 char buf[64];
860
861 if (!props)
862 return;
863 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100864 /*
865 * TODO Properties without a print method are just for dirty
866 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
867 * marked for removal. The test props->info->print should be
868 * removed along with it.
869 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200870 if (props->info->print) {
871 props->info->print(dev, props, buf, sizeof(buf));
872 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
873 }
874 props++;
875 }
876}
877
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100878static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
879{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100880 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200881 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
882 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100883 indent += 2;
884 if (dev->num_gpio_in) {
885 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
886 }
887 if (dev->num_gpio_out) {
888 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
889 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200890 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
891 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200892 if (dev->parent_bus->info->print_dev)
893 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000894 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100895 qbus_print(mon, child, indent);
896 }
897}
898
899static void qbus_print(Monitor *mon, BusState *bus, int indent)
900{
901 struct DeviceState *dev;
902
903 qdev_printf("bus: %s\n", bus->name);
904 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200905 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200906 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100907 qdev_print(mon, dev, indent);
908 }
909}
910#undef qdev_printf
911
912void do_info_qtree(Monitor *mon)
913{
914 if (main_system_bus)
915 qbus_print(mon, main_system_bus, 0);
916}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200917
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200918void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200919{
920 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200921
922 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100923 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200924 }
925}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200926
Markus Armbruster8bc27242010-02-10 20:52:01 +0100927int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200928{
929 QemuOpts *opts;
930
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200931 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100932 if (!opts) {
933 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100934 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100935 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
936 qemu_opts_del(opts);
937 return 0;
938 }
939 if (!qdev_device_add(opts)) {
940 qemu_opts_del(opts);
941 return -1;
942 }
943 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200944}
945
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100946int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200947{
948 const char *id = qdict_get_str(qdict, "id");
949 DeviceState *dev;
950
951 dev = qdev_find_recursive(main_system_bus, id);
952 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100953 qerror_report(QERR_DEVICE_NOT_FOUND, id);
954 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200955 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100956 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200957}
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200958
959static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
960{
961 int l = 0;
962
963 if (dev && dev->parent_bus) {
964 char *d;
965 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
966 if (dev->parent_bus->info->get_fw_dev_path) {
967 d = dev->parent_bus->info->get_fw_dev_path(dev);
968 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500969 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200970 } else {
971 l += snprintf(p + l, size - l, "%s", dev->info->name);
972 }
973 }
974 l += snprintf(p + l , size - l, "/");
975
976 return l;
977}
978
979char* qdev_get_fw_dev_path(DeviceState *dev)
980{
981 char path[128];
982 int l;
983
984 l = qdev_get_fw_dev_path_helper(dev, path, 128);
985
986 path[l-1] = '\0';
987
988 return strdup(path);
989}
Anthony Liguori85ed3032011-12-12 14:29:25 -0600990
991void qdev_ref(DeviceState *dev)
992{
993 dev->ref++;
994}
995
996void qdev_unref(DeviceState *dev)
997{
998 g_assert(dev->ref > 0);
999 dev->ref--;
1000}
Anthony Liguori44677de2011-12-12 14:29:26 -06001001
1002void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1003 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1004 DevicePropertyRelease *release,
1005 void *opaque, Error **errp)
1006{
1007 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1008
1009 prop->name = g_strdup(name);
1010 prop->type = g_strdup(type);
1011
1012 prop->get = get;
1013 prop->set = set;
1014 prop->release = release;
1015 prop->opaque = opaque;
1016
1017 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1018}
1019
1020static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1021{
1022 DeviceProperty *prop;
1023
1024 QTAILQ_FOREACH(prop, &dev->properties, node) {
1025 if (strcmp(prop->name, name) == 0) {
1026 return prop;
1027 }
1028 }
1029
1030 return NULL;
1031}
1032
1033void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1034 Error **errp)
1035{
1036 DeviceProperty *prop = qdev_property_find(dev, name);
1037
1038 if (prop == NULL) {
1039 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1040 return;
1041 }
1042
1043 if (!prop->get) {
1044 error_set(errp, QERR_PERMISSION_DENIED);
1045 } else {
1046 prop->get(dev, v, prop->opaque, name, errp);
1047 }
1048}
1049
1050void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1051 Error **errp)
1052{
1053 DeviceProperty *prop = qdev_property_find(dev, name);
1054
1055 if (prop == NULL) {
1056 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1057 return;
1058 }
1059
1060 if (!prop->set) {
1061 error_set(errp, QERR_PERMISSION_DENIED);
1062 } else {
1063 prop->set(dev, prop->opaque, v, name, errp);
1064 }
1065}
1066
1067const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1068{
1069 DeviceProperty *prop = qdev_property_find(dev, name);
1070
1071 if (prop == NULL) {
1072 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1073 return NULL;
1074 }
1075
1076 return prop->type;
1077}