blob: 167f4599966df5b73d626698318087f2ccd4499d [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
Paul Brookaae94602009-05-14 22:35:06 +0100113 return dev;
114}
115
Markus Armbruster0c175422010-02-19 19:12:18 +0100116/* Create a new device. This only initializes the device state structure
117 and allows properties to be set. qdev_init should be called to
118 initialize the actual device emulation. */
119DeviceState *qdev_create(BusState *bus, const char *name)
120{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000121 DeviceState *dev;
122
123 dev = qdev_try_create(bus, name);
124 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100125 if (bus) {
126 hw_error("Unknown device '%s' for bus '%s'\n", name,
127 bus->info->name);
128 } else {
129 hw_error("Unknown device '%s' for default sysbus\n", name);
130 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000131 }
132
133 return dev;
134}
135
136DeviceState *qdev_try_create(BusState *bus, const char *name)
137{
Markus Armbruster0c175422010-02-19 19:12:18 +0100138 DeviceInfo *info;
139
140 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100141 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100142 }
143
144 info = qdev_find_info(bus->info, name);
145 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000146 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100147 }
148
149 return qdev_create_from_info(bus, info);
150}
151
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100152static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200153{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100154 error_printf("name \"%s\", bus %s",
155 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200156 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100157 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200158 }
159 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100160 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200161 }
162 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100163 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200164 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100165 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200166}
167
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200168static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200169{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200170 DeviceState *dev = opaque;
171
172 if (strcmp(name, "driver") == 0)
173 return 0;
174 if (strcmp(name, "bus") == 0)
175 return 0;
176
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100177 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200178 return -1;
179 }
180 return 0;
181}
182
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100183int qdev_device_help(QemuOpts *opts)
184{
185 const char *driver;
186 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100187 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100188
189 driver = qemu_opt_get(opts, "driver");
190 if (driver && !strcmp(driver, "?")) {
191 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100192 if (info->no_user) {
193 continue; /* not available, don't show */
194 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100195 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100196 }
197 return 1;
198 }
199
Markus Armbruster542379f2011-11-08 11:00:38 +0100200 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100201 return 0;
202 }
203
204 info = qdev_find_info(NULL, driver);
205 if (!info) {
206 return 0;
207 }
208
209 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100210 /*
211 * TODO Properties without a parser are just for dirty hacks.
212 * qdev_prop_ptr is the only such PropertyInfo. It's marked
213 * for removal. This conditional should be removed along with
214 * it.
215 */
216 if (!prop->info->parse) {
217 continue; /* no way to set it, don't show */
218 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100219 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100220 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200221 for (prop = info->bus_info->props; prop && prop->name; prop++) {
222 if (!prop->info->parse) {
223 continue; /* no way to set it, don't show */
224 }
225 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
226 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100227 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100228}
229
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200230DeviceState *qdev_device_add(QemuOpts *opts)
231{
232 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200233 DeviceInfo *info;
234 DeviceState *qdev;
235 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200236
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200237 driver = qemu_opt_get(opts, "driver");
238 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100239 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200240 return NULL;
241 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200242
243 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200244 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100245 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100246 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100247 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200248 return NULL;
249 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200250
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200251 /* find bus */
252 path = qemu_opt_get(opts, "bus");
253 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200254 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100255 if (!bus) {
256 return NULL;
257 }
258 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100259 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
260 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100261 return NULL;
262 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200263 } else {
264 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100265 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100266 qerror_report(QERR_NO_BUS_FOR_DEVICE,
267 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100268 return NULL;
269 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200270 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200271 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100272 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200273 return NULL;
274 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200275
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200276 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100277 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200278 id = qemu_opts_id(opts);
279 if (id) {
280 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200281 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200282 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
283 qdev_free(qdev);
284 return NULL;
285 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200286 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100287 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200288 return NULL;
289 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200290 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200291 return qdev;
292}
293
Paul Brookaae94602009-05-14 22:35:06 +0100294/* Initialize a device. Device properties should be set before calling
295 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200296 calling this function.
297 On failure, destroy the device and return negative value.
298 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200299int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100300{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200301 int rc;
302
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200303 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200304 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200305 if (rc < 0) {
306 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200307 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200308 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200309 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600310 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200311 dev->instance_id_alias,
312 dev->alias_required_for_version);
313 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200314 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200315 if (dev->hotplugged && dev->info->reset) {
316 dev->info->reset(dev);
317 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200318 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100319}
320
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200321void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
322 int required_for_version)
323{
324 assert(dev->state == DEV_STATE_CREATED);
325 dev->instance_id_alias = alias_id;
326 dev->alias_required_for_version = required_for_version;
327}
328
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200329int qdev_unplug(DeviceState *dev)
330{
331 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100332 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200333 return -1;
334 }
Amit Shah593831d2009-11-02 14:56:41 +0530335 assert(dev->info->unplug != NULL);
336
Anthony Liguori85ed3032011-12-12 14:29:25 -0600337 if (dev->ref != 0) {
338 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
339 return -1;
340 }
341
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700342 qdev_hot_removed = true;
343
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200344 return dev->info->unplug(dev);
345}
346
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900347static int qdev_reset_one(DeviceState *dev, void *opaque)
348{
349 if (dev->info->reset) {
350 dev->info->reset(dev);
351 }
352
353 return 0;
354}
355
356BusState *sysbus_get_default(void)
357{
Stefan Weil68694892010-12-16 19:33:22 +0100358 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900359 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100360 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900361 return main_system_bus;
362}
363
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900364static int qbus_reset_one(BusState *bus, void *opaque)
365{
366 if (bus->info->reset) {
367 return bus->info->reset(bus);
368 }
369 return 0;
370}
371
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900372void qdev_reset_all(DeviceState *dev)
373{
374 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
375}
376
Isaku Yamahata80376c32010-12-20 14:33:35 +0900377void qbus_reset_all_fn(void *opaque)
378{
379 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200380 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900381}
382
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200383/* can be used as ->unplug() callback for the simple cases */
384int qdev_simple_unplug_cb(DeviceState *dev)
385{
386 /* just zap it */
387 qdev_free(dev);
388 return 0;
389}
390
Michael Tokarev3b29a102011-04-06 17:51:59 +0400391
392/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200393 returning an error value. This is okay during machine creation.
394 Don't use for hotplug, because there callers need to recover from
395 failure. Exception: if you know the device's init() callback can't
396 fail, then qdev_init_nofail() can't fail either, and is therefore
397 usable even then. But relying on the device implementation that
398 way is somewhat unclean, and best avoided. */
399void qdev_init_nofail(DeviceState *dev)
400{
401 DeviceInfo *info = dev->info;
402
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200403 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200404 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200405 exit(1);
406 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200407}
408
Anthony Liguori44677de2011-12-12 14:29:26 -0600409static void qdev_property_del_all(DeviceState *dev)
410{
411 while (!QTAILQ_EMPTY(&dev->properties)) {
412 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
413
414 QTAILQ_REMOVE(&dev->properties, prop, node);
415
416 if (prop->release) {
417 prop->release(dev, prop->name, prop->opaque);
418 }
419
420 g_free(prop->name);
421 g_free(prop->type);
422 g_free(prop);
423 }
424}
425
Paul Brook02e2da42009-05-23 00:05:19 +0100426/* Unlink device from bus and free the structure. */
427void qdev_free(DeviceState *dev)
428{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200429 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200430 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200431
Anthony Liguori44677de2011-12-12 14:29:26 -0600432 qdev_property_del_all(dev);
433
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200434 if (dev->state == DEV_STATE_INITIALIZED) {
435 while (dev->num_child_bus) {
436 bus = QLIST_FIRST(&dev->child_bus);
437 qbus_free(bus);
438 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200439 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600440 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200441 if (dev->info->exit)
442 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200443 if (dev->opts)
444 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200445 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200446 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200447 for (prop = dev->info->props; prop && prop->name; prop++) {
448 if (prop->info->free) {
449 prop->info->free(dev, prop);
450 }
451 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500452 g_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100453}
454
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200455void qdev_machine_creation_done(void)
456{
457 /*
458 * ok, initial machine setup is done, starting from now we can
459 * only create hotpluggable devices
460 */
461 qdev_hotplug = 1;
462}
463
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700464bool qdev_machine_modified(void)
465{
466 return qdev_hot_added || qdev_hot_removed;
467}
468
Paul Brookaae94602009-05-14 22:35:06 +0100469/* Get a character (serial) device interface. */
470CharDriverState *qdev_init_chardev(DeviceState *dev)
471{
472 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530473
474 /* FIXME: This function needs to go away: use chardev properties! */
475 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100476}
477
Paul Brook02e2da42009-05-23 00:05:19 +0100478BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100479{
Paul Brook02e2da42009-05-23 00:05:19 +0100480 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100481}
482
Paul Brookaae94602009-05-14 22:35:06 +0100483void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
484{
485 assert(dev->num_gpio_in == 0);
486 dev->num_gpio_in = n;
487 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
488}
489
490void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
491{
492 assert(dev->num_gpio_out == 0);
493 dev->num_gpio_out = n;
494 dev->gpio_out = pins;
495}
496
497qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
498{
499 assert(n >= 0 && n < dev->num_gpio_in);
500 return dev->gpio_in[n];
501}
502
503void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
504{
505 assert(n >= 0 && n < dev->num_gpio_out);
506 dev->gpio_out[n] = pin;
507}
508
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200509void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
510{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200511 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200512 if (nd->vlan)
513 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
514 if (nd->netdev)
515 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530516 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200517 qdev_prop_exists(dev, "vectors")) {
518 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
519 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100520 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200521}
522
Paul Brook02e2da42009-05-23 00:05:19 +0100523BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100524{
Paul Brook02e2da42009-05-23 00:05:19 +0100525 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100526
Blue Swirl72cf2d42009-09-12 07:36:22 +0000527 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100528 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100529 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100530 }
531 }
532 return NULL;
533}
534
Anthony Liguori81699d82010-11-19 18:55:58 +0900535int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
536 qbus_walkerfn *busfn, void *opaque)
537{
538 DeviceState *dev;
539 int err;
540
541 if (busfn) {
542 err = busfn(bus, opaque);
543 if (err) {
544 return err;
545 }
546 }
547
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200548 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900549 err = qdev_walk_children(dev, devfn, busfn, opaque);
550 if (err < 0) {
551 return err;
552 }
553 }
554
555 return 0;
556}
557
558int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
559 qbus_walkerfn *busfn, void *opaque)
560{
561 BusState *bus;
562 int err;
563
564 if (devfn) {
565 err = devfn(dev, opaque);
566 if (err) {
567 return err;
568 }
569 }
570
571 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
572 err = qbus_walk_children(bus, devfn, busfn, opaque);
573 if (err < 0) {
574 return err;
575 }
576 }
577
578 return 0;
579}
580
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200581static BusState *qbus_find_recursive(BusState *bus, const char *name,
582 const BusInfo *info)
583{
584 DeviceState *dev;
585 BusState *child, *ret;
586 int match = 1;
587
588 if (name && (strcmp(bus->name, name) != 0)) {
589 match = 0;
590 }
591 if (info && (bus->info != info)) {
592 match = 0;
593 }
594 if (match) {
595 return bus;
596 }
597
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200598 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000599 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200600 ret = qbus_find_recursive(child, name, info);
601 if (ret) {
602 return ret;
603 }
604 }
605 }
606 return NULL;
607}
608
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900609DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200610{
611 DeviceState *dev, *ret;
612 BusState *child;
613
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200614 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200615 if (dev->id && strcmp(dev->id, id) == 0)
616 return dev;
617 QLIST_FOREACH(child, &dev->child_bus, sibling) {
618 ret = qdev_find_recursive(child, id);
619 if (ret) {
620 return ret;
621 }
622 }
623 }
624 return NULL;
625}
626
Markus Armbruster53db16b2010-02-18 18:55:59 +0100627static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200628{
629 BusState *child;
630 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200631
Markus Armbruster53db16b2010-02-18 18:55:59 +0100632 error_printf("child busses at \"%s\":",
633 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000634 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100635 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200636 sep = ", ";
637 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100638 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200639}
640
Markus Armbruster53db16b2010-02-18 18:55:59 +0100641static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200642{
643 DeviceState *dev;
644 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200645
Markus Armbruster53db16b2010-02-18 18:55:59 +0100646 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200647 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100648 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200649 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100650 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200651 sep = ", ";
652 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100653 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200654}
655
656static BusState *qbus_find_bus(DeviceState *dev, char *elem)
657{
658 BusState *child;
659
Blue Swirl72cf2d42009-09-12 07:36:22 +0000660 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200661 if (strcmp(child->name, elem) == 0) {
662 return child;
663 }
664 }
665 return NULL;
666}
667
668static DeviceState *qbus_find_dev(BusState *bus, char *elem)
669{
670 DeviceState *dev;
671
672 /*
673 * try to match in order:
674 * (1) instance id, if present
675 * (2) driver name
676 * (3) driver alias, if present
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->id && strcmp(dev->id, elem) == 0) {
680 return dev;
681 }
682 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200683 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200684 if (strcmp(dev->info->name, elem) == 0) {
685 return dev;
686 }
687 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200688 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200689 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
690 return dev;
691 }
692 }
693 return NULL;
694}
695
696static BusState *qbus_find(const char *path)
697{
698 DeviceState *dev;
699 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100700 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200701 int pos, len;
702
703 /* find start element */
704 if (path[0] == '/') {
705 bus = main_system_bus;
706 pos = 0;
707 } else {
708 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100709 assert(!path[0]);
710 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200711 }
712 bus = qbus_find_recursive(main_system_bus, elem, NULL);
713 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100714 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200715 return NULL;
716 }
717 pos = len;
718 }
719
720 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100721 assert(path[pos] == '/' || !path[pos]);
722 while (path[pos] == '/') {
723 pos++;
724 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200725 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200726 return bus;
727 }
728
729 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100730 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
731 assert(0);
732 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200733 }
734 pos += len;
735 dev = qbus_find_dev(bus, elem);
736 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100737 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100738 if (!monitor_cur_is_qmp()) {
739 qbus_list_dev(bus);
740 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200741 return NULL;
742 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100743
744 assert(path[pos] == '/' || !path[pos]);
745 while (path[pos] == '/') {
746 pos++;
747 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200748 if (path[pos] == '\0') {
749 /* last specified element is a device. If it has exactly
750 * one child bus accept it nevertheless */
751 switch (dev->num_child_bus) {
752 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100753 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200754 return NULL;
755 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000756 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200757 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100758 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100759 if (!monitor_cur_is_qmp()) {
760 qbus_list_bus(dev);
761 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200762 return NULL;
763 }
764 }
765
766 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100767 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
768 assert(0);
769 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200770 }
771 pos += len;
772 bus = qbus_find_bus(dev, elem);
773 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100774 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100775 if (!monitor_cur_is_qmp()) {
776 qbus_list_bus(dev);
777 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200778 return NULL;
779 }
780 }
781}
782
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200783void qbus_create_inplace(BusState *bus, BusInfo *info,
784 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100785{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200786 char *buf;
787 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100788
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200789 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100790 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200791
792 if (name) {
793 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500794 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200795 } else if (parent && parent->id) {
796 /* parent device has id -> use it for bus name */
797 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500798 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200799 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
800 bus->name = buf;
801 } else {
802 /* no id -> use lowercase bus type for bus name */
803 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500804 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200805 len = snprintf(buf, len, "%s.%d", info->name,
806 parent ? parent->num_child_bus : 0);
807 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200808 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200809 bus->name = buf;
810 }
811
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200812 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100813 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000814 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200815 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900816 } else if (bus != main_system_bus) {
817 /* TODO: once all bus devices are qdevified,
818 only reset handler for main_system_bus should be registered here. */
819 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100820 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200821}
822
823BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
824{
825 BusState *bus;
826
Anthony Liguori7267c092011-08-20 22:09:37 -0500827 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200828 bus->qdev_allocated = 1;
829 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100830 return bus;
831}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100832
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900833static void main_system_bus_create(void)
834{
835 /* assign main_system_bus before qbus_create_inplace()
836 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500837 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900838 main_system_bus->qdev_allocated = 1;
839 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
840 "main-system-bus");
841}
842
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200843void qbus_free(BusState *bus)
844{
845 DeviceState *dev;
846
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200847 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200848 qdev_free(dev);
849 }
850 if (bus->parent) {
851 QLIST_REMOVE(bus, sibling);
852 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900853 } else {
854 assert(bus != main_system_bus); /* main_system_bus is never freed */
855 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200856 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500857 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200858 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500859 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200860 }
861}
862
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100863#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
864static void qbus_print(Monitor *mon, BusState *bus, int indent);
865
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200866static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
867 const char *prefix, int indent)
868{
869 char buf[64];
870
871 if (!props)
872 return;
873 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100874 /*
875 * TODO Properties without a print method are just for dirty
876 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
877 * marked for removal. The test props->info->print should be
878 * removed along with it.
879 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200880 if (props->info->print) {
881 props->info->print(dev, props, buf, sizeof(buf));
882 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
883 }
884 props++;
885 }
886}
887
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100888static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
889{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100890 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200891 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
892 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100893 indent += 2;
894 if (dev->num_gpio_in) {
895 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
896 }
897 if (dev->num_gpio_out) {
898 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
899 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200900 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
901 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200902 if (dev->parent_bus->info->print_dev)
903 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000904 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100905 qbus_print(mon, child, indent);
906 }
907}
908
909static void qbus_print(Monitor *mon, BusState *bus, int indent)
910{
911 struct DeviceState *dev;
912
913 qdev_printf("bus: %s\n", bus->name);
914 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200915 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200916 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100917 qdev_print(mon, dev, indent);
918 }
919}
920#undef qdev_printf
921
922void do_info_qtree(Monitor *mon)
923{
924 if (main_system_bus)
925 qbus_print(mon, main_system_bus, 0);
926}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200927
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200928void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200929{
930 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200931
932 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100933 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200934 }
935}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200936
Markus Armbruster8bc27242010-02-10 20:52:01 +0100937int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200938{
939 QemuOpts *opts;
940
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200941 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100942 if (!opts) {
943 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100944 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100945 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
946 qemu_opts_del(opts);
947 return 0;
948 }
949 if (!qdev_device_add(opts)) {
950 qemu_opts_del(opts);
951 return -1;
952 }
953 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200954}
955
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100956int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200957{
958 const char *id = qdict_get_str(qdict, "id");
959 DeviceState *dev;
960
961 dev = qdev_find_recursive(main_system_bus, id);
962 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100963 qerror_report(QERR_DEVICE_NOT_FOUND, id);
964 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200965 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100966 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200967}
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200968
969static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
970{
971 int l = 0;
972
973 if (dev && dev->parent_bus) {
974 char *d;
975 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
976 if (dev->parent_bus->info->get_fw_dev_path) {
977 d = dev->parent_bus->info->get_fw_dev_path(dev);
978 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500979 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200980 } else {
981 l += snprintf(p + l, size - l, "%s", dev->info->name);
982 }
983 }
984 l += snprintf(p + l , size - l, "/");
985
986 return l;
987}
988
989char* qdev_get_fw_dev_path(DeviceState *dev)
990{
991 char path[128];
992 int l;
993
994 l = qdev_get_fw_dev_path_helper(dev, path, 128);
995
996 path[l-1] = '\0';
997
998 return strdup(path);
999}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001000
1001void qdev_ref(DeviceState *dev)
1002{
1003 dev->ref++;
1004}
1005
1006void qdev_unref(DeviceState *dev)
1007{
1008 g_assert(dev->ref > 0);
1009 dev->ref--;
1010}
Anthony Liguori44677de2011-12-12 14:29:26 -06001011
1012void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1013 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1014 DevicePropertyRelease *release,
1015 void *opaque, Error **errp)
1016{
1017 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1018
1019 prop->name = g_strdup(name);
1020 prop->type = g_strdup(type);
1021
1022 prop->get = get;
1023 prop->set = set;
1024 prop->release = release;
1025 prop->opaque = opaque;
1026
1027 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1028}
1029
1030static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1031{
1032 DeviceProperty *prop;
1033
1034 QTAILQ_FOREACH(prop, &dev->properties, node) {
1035 if (strcmp(prop->name, name) == 0) {
1036 return prop;
1037 }
1038 }
1039
1040 return NULL;
1041}
1042
1043void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1044 Error **errp)
1045{
1046 DeviceProperty *prop = qdev_property_find(dev, name);
1047
1048 if (prop == NULL) {
1049 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1050 return;
1051 }
1052
1053 if (!prop->get) {
1054 error_set(errp, QERR_PERMISSION_DENIED);
1055 } else {
1056 prop->get(dev, v, prop->opaque, name, errp);
1057 }
1058}
1059
1060void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1061 Error **errp)
1062{
1063 DeviceProperty *prop = qdev_property_find(dev, name);
1064
1065 if (prop == NULL) {
1066 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1067 return;
1068 }
1069
1070 if (!prop->set) {
1071 error_set(errp, QERR_PERMISSION_DENIED);
1072 } else {
1073 prop->set(dev, prop->opaque, v, name, errp);
1074 }
1075}
1076
1077const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1078{
1079 DeviceProperty *prop = qdev_property_find(dev, name);
1080
1081 if (prop == NULL) {
1082 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1083 return NULL;
1084 }
1085
1086 return prop->type;
1087}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001088
1089/**
1090 * Legacy property handling
1091 */
1092
1093static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1094 const char *name, Error **errp)
1095{
1096 Property *prop = opaque;
1097
1098 if (prop->info->print) {
1099 char buffer[1024];
1100 char *ptr = buffer;
1101
1102 prop->info->print(dev, prop, buffer, sizeof(buffer));
1103 visit_type_str(v, &ptr, name, errp);
1104 } else {
1105 error_set(errp, QERR_PERMISSION_DENIED);
1106 }
1107}
1108
1109static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1110 const char *name, Error **errp)
1111{
1112 Property *prop = opaque;
1113
1114 if (dev->state != DEV_STATE_CREATED) {
1115 error_set(errp, QERR_PERMISSION_DENIED);
1116 return;
1117 }
1118
1119 if (prop->info->parse) {
1120 Error *local_err = NULL;
1121 char *ptr = NULL;
1122
1123 visit_type_str(v, &ptr, name, &local_err);
1124 if (!local_err) {
1125 int ret;
1126 ret = prop->info->parse(dev, prop, ptr);
1127 if (ret != 0) {
1128 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
1129 name, prop->info->name);
1130 }
1131 g_free(ptr);
1132 } else {
1133 error_propagate(errp, local_err);
1134 }
1135 } else {
1136 error_set(errp, QERR_PERMISSION_DENIED);
1137 }
1138}
1139
1140/**
1141 * @qdev_add_legacy_property - adds a legacy property
1142 *
1143 * Do not use this is new code! Properties added through this interface will
1144 * be given types in the "legacy<>" type namespace.
1145 *
1146 * Legacy properties are always processed as strings. The format of the string
1147 * depends on the property type.
1148 */
1149void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1150 Error **errp)
1151{
1152 gchar *type;
1153
1154 type = g_strdup_printf("legacy<%s>", prop->info->name);
1155
1156 qdev_property_add(dev, prop->name, type,
1157 qdev_get_legacy_property,
1158 qdev_set_legacy_property,
1159 NULL,
1160 prop, errp);
1161
1162 g_free(type);
1163}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001164
1165DeviceState *qdev_get_root(void)
1166{
1167 static DeviceState *qdev_root;
1168
1169 if (!qdev_root) {
1170 qdev_root = qdev_create(NULL, "container");
1171 qdev_init_nofail(qdev_root);
1172 }
1173
1174 return qdev_root;
1175}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001176
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001177static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1178 const char *name, Error **errp)
1179{
1180 DeviceState *child = opaque;
1181 gchar *path;
1182
1183 path = qdev_get_canonical_path(child);
1184 visit_type_str(v, &path, name, errp);
1185 g_free(path);
1186}
1187
1188void qdev_property_add_child(DeviceState *dev, const char *name,
1189 DeviceState *child, Error **errp)
1190{
1191 gchar *type;
1192
1193 type = g_strdup_printf("child<%s>", child->info->name);
1194
1195 qdev_property_add(dev, name, type, qdev_get_child_property,
1196 NULL, NULL, child, errp);
1197
1198 qdev_ref(child);
1199
1200 g_free(type);
1201}
1202
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001203static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
1204{
1205 DeviceProperty *prop;
1206
1207 if (parent == dev) {
1208 return g_strdup("");
1209 }
1210
1211 QTAILQ_FOREACH(prop, &parent->properties, node) {
1212 gchar *subpath;
1213
1214 if (!strstart(prop->type, "child<", NULL)) {
1215 continue;
1216 }
1217
1218 /* Check to see if the device is one of parent's children */
1219 if (prop->opaque == dev) {
1220 return g_strdup(prop->name);
1221 }
1222
1223 /* Check to see if the device is a child of our child */
1224 subpath = qdev_get_path_in(prop->opaque, dev);
1225 if (subpath) {
1226 gchar *path;
1227
1228 path = g_strdup_printf("%s/%s", prop->name, subpath);
1229 g_free(subpath);
1230
1231 return path;
1232 }
1233 }
1234
1235 return NULL;
1236}
1237
1238gchar *qdev_get_canonical_path(DeviceState *dev)
1239{
1240 gchar *path, *newpath;
1241
1242 path = qdev_get_path_in(qdev_get_root(), dev);
1243 g_assert(path != NULL);
1244
1245 newpath = g_strdup_printf("/%s", path);
1246 g_free(path);
1247
1248 return newpath;
1249}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001250
1251static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1252 gchar **parts,
1253 int index)
1254{
1255 DeviceProperty *prop;
1256 DeviceState *child;
1257
1258 if (parts[index] == NULL) {
1259 return parent;
1260 }
1261
1262 if (strcmp(parts[index], "") == 0) {
1263 return qdev_resolve_abs_path(parent, parts, index + 1);
1264 }
1265
1266 prop = qdev_property_find(parent, parts[index]);
1267 if (prop == NULL) {
1268 return NULL;
1269 }
1270
1271 child = NULL;
1272 if (strstart(prop->type, "link<", NULL)) {
1273 DeviceState **pchild = prop->opaque;
1274 if (*pchild) {
1275 child = *pchild;
1276 }
1277 } else if (strstart(prop->type, "child<", NULL)) {
1278 child = prop->opaque;
1279 }
1280
1281 if (!child) {
1282 return NULL;
1283 }
1284
1285 return qdev_resolve_abs_path(child, parts, index + 1);
1286}
1287
1288static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1289 gchar **parts,
1290 bool *ambiguous)
1291{
1292 DeviceState *dev;
1293 DeviceProperty *prop;
1294
1295 dev = qdev_resolve_abs_path(parent, parts, 0);
1296
1297 QTAILQ_FOREACH(prop, &parent->properties, node) {
1298 DeviceState *found;
1299
1300 if (!strstart(prop->type, "child<", NULL)) {
1301 continue;
1302 }
1303
1304 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1305 if (found) {
1306 if (dev) {
1307 if (ambiguous) {
1308 *ambiguous = true;
1309 }
1310 return NULL;
1311 }
1312 dev = found;
1313 }
1314
1315 if (ambiguous && *ambiguous) {
1316 return NULL;
1317 }
1318 }
1319
1320 return dev;
1321}
1322
1323DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1324{
1325 bool partial_path = true;
1326 DeviceState *dev;
1327 gchar **parts;
1328
1329 parts = g_strsplit(path, "/", 0);
1330 if (parts == NULL || parts[0] == NULL) {
1331 g_strfreev(parts);
1332 return qdev_get_root();
1333 }
1334
1335 if (strcmp(parts[0], "") == 0) {
1336 partial_path = false;
1337 }
1338
1339 if (partial_path) {
1340 if (ambiguous) {
1341 *ambiguous = false;
1342 }
1343 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1344 } else {
1345 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1346 }
1347
1348 g_strfreev(parts);
1349
1350 return dev;
1351}
1352