blob: af174869761423e241c3857b1372c4a1bddab95a [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;
34
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020035/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000036static BusState *main_system_bus;
Paul Brook4d6ae672009-05-14 22:35:06 +010037
Gerd Hoffmann0958b4c2009-10-26 15:56:45 +010038DeviceInfo *device_info_list;
Paul Brookaae94602009-05-14 22:35:06 +010039
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020040static BusState *qbus_find_recursive(BusState *bus, const char *name,
41 const BusInfo *info);
42static BusState *qbus_find(const char *path);
43
Paul Brookaae94602009-05-14 22:35:06 +010044/* Register a new device type. */
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020045void qdev_register(DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010046{
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020047 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020048 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010049
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020050 info->next = device_info_list;
51 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010052}
53
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020054static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
55{
56 DeviceInfo *info;
57
Gerd Hoffmann3320e562009-07-15 13:43:33 +020058 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020059 for (info = device_info_list; info != NULL; info = info->next) {
60 if (bus_info && info->bus_info != bus_info)
61 continue;
62 if (strcmp(info->name, name) != 0)
63 continue;
64 return info;
65 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +020066
67 /* failing that check the aliases */
68 for (info = device_info_list; info != NULL; info = info->next) {
69 if (bus_info && info->bus_info != bus_info)
70 continue;
71 if (!info->alias)
72 continue;
73 if (strcmp(info->alias, name) != 0)
74 continue;
75 return info;
76 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020077 return NULL;
78}
79
Markus Armbruster0c175422010-02-19 19:12:18 +010080static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010081{
Paul Brookaae94602009-05-14 22:35:06 +010082 DeviceState *dev;
83
Markus Armbruster0c175422010-02-19 19:12:18 +010084 assert(bus->info == info->bus_info);
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020085 dev = qemu_mallocz(info->size);
86 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +010087 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020088 qdev_prop_set_defaults(dev, dev->info->props);
89 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010090 qdev_prop_set_globals(dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +000091 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020092 if (qdev_hotplug) {
93 assert(bus->allow_hotplug);
94 dev->hotplugged = 1;
95 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +020096 dev->instance_id_alias = -1;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +020097 dev->state = DEV_STATE_CREATED;
Paul Brookaae94602009-05-14 22:35:06 +010098 return dev;
99}
100
Markus Armbruster0c175422010-02-19 19:12:18 +0100101/* Create a new device. This only initializes the device state structure
102 and allows properties to be set. qdev_init should be called to
103 initialize the actual device emulation. */
104DeviceState *qdev_create(BusState *bus, const char *name)
105{
106 DeviceInfo *info;
107
108 if (!bus) {
109 if (!main_system_bus) {
110 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
111 }
112 bus = main_system_bus;
113 }
114
115 info = qdev_find_info(bus->info, name);
116 if (!info) {
117 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
118 }
119
120 return qdev_create_from_info(bus, info);
121}
122
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100123static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200124{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100125 error_printf("name \"%s\", bus %s",
126 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200127 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100128 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200129 }
130 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100131 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200132 }
133 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100134 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200135 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100136 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200137}
138
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200139static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200140{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200141 DeviceState *dev = opaque;
142
143 if (strcmp(name, "driver") == 0)
144 return 0;
145 if (strcmp(name, "bus") == 0)
146 return 0;
147
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100148 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200149 return -1;
150 }
151 return 0;
152}
153
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100154int qdev_device_help(QemuOpts *opts)
155{
156 const char *driver;
157 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100158 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100159
160 driver = qemu_opt_get(opts, "driver");
161 if (driver && !strcmp(driver, "?")) {
162 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100163 if (info->no_user) {
164 continue; /* not available, don't show */
165 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100166 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100167 }
168 return 1;
169 }
170
Markus Armbruster08350cf2010-01-29 19:49:00 +0100171 if (!qemu_opt_get(opts, "?")) {
172 return 0;
173 }
174
175 info = qdev_find_info(NULL, driver);
176 if (!info) {
177 return 0;
178 }
179
180 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100181 /*
182 * TODO Properties without a parser are just for dirty hacks.
183 * qdev_prop_ptr is the only such PropertyInfo. It's marked
184 * for removal. This conditional should be removed along with
185 * it.
186 */
187 if (!prop->info->parse) {
188 continue; /* no way to set it, don't show */
189 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100190 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100191 }
192 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100193}
194
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200195DeviceState *qdev_device_add(QemuOpts *opts)
196{
197 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200198 DeviceInfo *info;
199 DeviceState *qdev;
200 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200201
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200202 driver = qemu_opt_get(opts, "driver");
203 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100204 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200205 return NULL;
206 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200207
208 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200209 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100210 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100211 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100212 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200213 return NULL;
214 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200215
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200216 /* find bus */
217 path = qemu_opt_get(opts, "bus");
218 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200219 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100220 if (!bus) {
221 return NULL;
222 }
223 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100224 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
225 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100226 return NULL;
227 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200228 } else {
229 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100230 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100231 qerror_report(QERR_NO_BUS_FOR_DEVICE,
232 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100233 return NULL;
234 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200235 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200236 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100237 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200238 return NULL;
239 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200240
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200241 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100242 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200243 id = qemu_opts_id(opts);
244 if (id) {
245 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200246 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200247 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
248 qdev_free(qdev);
249 return NULL;
250 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200251 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100252 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200253 return NULL;
254 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200255 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200256 return qdev;
257}
258
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300259static void qdev_reset(void *opaque)
260{
261 DeviceState *dev = opaque;
262 if (dev->info->reset)
263 dev->info->reset(dev);
264}
265
Paul Brookaae94602009-05-14 22:35:06 +0100266/* Initialize a device. Device properties should be set before calling
267 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200268 calling this function.
269 On failure, destroy the device and return negative value.
270 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200271int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100272{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200273 int rc;
274
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200275 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200276 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200277 if (rc < 0) {
278 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200279 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200280 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300281 qemu_register_reset(qdev_reset, dev);
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200282 if (dev->info->vmsd) {
283 vmstate_register_with_alias_id(-1, dev->info->vmsd, dev,
284 dev->instance_id_alias,
285 dev->alias_required_for_version);
286 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200287 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200288 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100289}
290
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200291void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
292 int required_for_version)
293{
294 assert(dev->state == DEV_STATE_CREATED);
295 dev->instance_id_alias = alias_id;
296 dev->alias_required_for_version = required_for_version;
297}
298
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200299int qdev_unplug(DeviceState *dev)
300{
301 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100302 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200303 return -1;
304 }
Amit Shah593831d2009-11-02 14:56:41 +0530305 assert(dev->info->unplug != NULL);
306
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200307 return dev->info->unplug(dev);
308}
309
310/* can be used as ->unplug() callback for the simple cases */
311int qdev_simple_unplug_cb(DeviceState *dev)
312{
313 /* just zap it */
314 qdev_free(dev);
315 return 0;
316}
317
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200318/* Like qdev_init(), but terminate program via hw_error() instead of
319 returning an error value. This is okay during machine creation.
320 Don't use for hotplug, because there callers need to recover from
321 failure. Exception: if you know the device's init() callback can't
322 fail, then qdev_init_nofail() can't fail either, and is therefore
323 usable even then. But relying on the device implementation that
324 way is somewhat unclean, and best avoided. */
325void qdev_init_nofail(DeviceState *dev)
326{
327 DeviceInfo *info = dev->info;
328
329 if (qdev_init(dev) < 0)
330 hw_error("Initialization of device %s failed\n", info->name);
331}
332
Paul Brook02e2da42009-05-23 00:05:19 +0100333/* Unlink device from bus and free the structure. */
334void qdev_free(DeviceState *dev)
335{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200336 BusState *bus;
337
338 if (dev->state == DEV_STATE_INITIALIZED) {
339 while (dev->num_child_bus) {
340 bus = QLIST_FIRST(&dev->child_bus);
341 qbus_free(bus);
342 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200343 if (dev->info->vmsd)
344 vmstate_unregister(dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200345 if (dev->info->exit)
346 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200347 if (dev->opts)
348 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200349 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300350 qemu_unregister_reset(qdev_reset, dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000351 QLIST_REMOVE(dev, sibling);
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200352 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100353}
354
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200355void qdev_machine_creation_done(void)
356{
357 /*
358 * ok, initial machine setup is done, starting from now we can
359 * only create hotpluggable devices
360 */
361 qdev_hotplug = 1;
362}
363
Paul Brookaae94602009-05-14 22:35:06 +0100364/* Get a character (serial) device interface. */
365CharDriverState *qdev_init_chardev(DeviceState *dev)
366{
367 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530368
369 /* FIXME: This function needs to go away: use chardev properties! */
370 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100371}
372
Paul Brook02e2da42009-05-23 00:05:19 +0100373BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100374{
Paul Brook02e2da42009-05-23 00:05:19 +0100375 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100376}
377
Paul Brookaae94602009-05-14 22:35:06 +0100378void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
379{
380 assert(dev->num_gpio_in == 0);
381 dev->num_gpio_in = n;
382 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
383}
384
385void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
386{
387 assert(dev->num_gpio_out == 0);
388 dev->num_gpio_out = n;
389 dev->gpio_out = pins;
390}
391
392qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
393{
394 assert(n >= 0 && n < dev->num_gpio_in);
395 return dev->gpio_in[n];
396}
397
398void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
399{
400 assert(n >= 0 && n < dev->num_gpio_out);
401 dev->gpio_out[n] = pin;
402}
403
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200404void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
405{
406 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
407 if (nd->vlan)
408 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
409 if (nd->netdev)
410 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530411 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200412 qdev_prop_exists(dev, "vectors")) {
413 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
414 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200415}
416
Paul Brookaae94602009-05-14 22:35:06 +0100417static int next_block_unit[IF_COUNT];
418
419/* Get a block device. This should only be used for single-drive devices
420 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
421 appropriate bus. */
422BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
423{
424 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200425 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100426
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200427 dinfo = drive_get(type, 0, unit);
428 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100429}
Paul Brook4d6ae672009-05-14 22:35:06 +0100430
Paul Brook02e2da42009-05-23 00:05:19 +0100431BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100432{
Paul Brook02e2da42009-05-23 00:05:19 +0100433 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100434
Blue Swirl72cf2d42009-09-12 07:36:22 +0000435 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100436 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100437 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100438 }
439 }
440 return NULL;
441}
442
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200443static BusState *qbus_find_recursive(BusState *bus, const char *name,
444 const BusInfo *info)
445{
446 DeviceState *dev;
447 BusState *child, *ret;
448 int match = 1;
449
450 if (name && (strcmp(bus->name, name) != 0)) {
451 match = 0;
452 }
453 if (info && (bus->info != info)) {
454 match = 0;
455 }
456 if (match) {
457 return bus;
458 }
459
Blue Swirl72cf2d42009-09-12 07:36:22 +0000460 QLIST_FOREACH(dev, &bus->children, sibling) {
461 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200462 ret = qbus_find_recursive(child, name, info);
463 if (ret) {
464 return ret;
465 }
466 }
467 }
468 return NULL;
469}
470
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200471static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
472{
473 DeviceState *dev, *ret;
474 BusState *child;
475
476 QLIST_FOREACH(dev, &bus->children, sibling) {
477 if (dev->id && strcmp(dev->id, id) == 0)
478 return dev;
479 QLIST_FOREACH(child, &dev->child_bus, sibling) {
480 ret = qdev_find_recursive(child, id);
481 if (ret) {
482 return ret;
483 }
484 }
485 }
486 return NULL;
487}
488
Markus Armbruster53db16b2010-02-18 18:55:59 +0100489static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200490{
491 BusState *child;
492 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200493
Markus Armbruster53db16b2010-02-18 18:55:59 +0100494 error_printf("child busses at \"%s\":",
495 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000496 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100497 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200498 sep = ", ";
499 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100500 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200501}
502
Markus Armbruster53db16b2010-02-18 18:55:59 +0100503static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200504{
505 DeviceState *dev;
506 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200507
Markus Armbruster53db16b2010-02-18 18:55:59 +0100508 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000509 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100510 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200511 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100512 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200513 sep = ", ";
514 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100515 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200516}
517
518static BusState *qbus_find_bus(DeviceState *dev, char *elem)
519{
520 BusState *child;
521
Blue Swirl72cf2d42009-09-12 07:36:22 +0000522 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200523 if (strcmp(child->name, elem) == 0) {
524 return child;
525 }
526 }
527 return NULL;
528}
529
530static DeviceState *qbus_find_dev(BusState *bus, char *elem)
531{
532 DeviceState *dev;
533
534 /*
535 * try to match in order:
536 * (1) instance id, if present
537 * (2) driver name
538 * (3) driver alias, if present
539 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000540 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200541 if (dev->id && strcmp(dev->id, elem) == 0) {
542 return dev;
543 }
544 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000545 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200546 if (strcmp(dev->info->name, elem) == 0) {
547 return dev;
548 }
549 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000550 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200551 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
552 return dev;
553 }
554 }
555 return NULL;
556}
557
558static BusState *qbus_find(const char *path)
559{
560 DeviceState *dev;
561 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100562 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200563 int pos, len;
564
565 /* find start element */
566 if (path[0] == '/') {
567 bus = main_system_bus;
568 pos = 0;
569 } else {
570 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100571 assert(!path[0]);
572 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200573 }
574 bus = qbus_find_recursive(main_system_bus, elem, NULL);
575 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100576 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200577 return NULL;
578 }
579 pos = len;
580 }
581
582 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100583 assert(path[pos] == '/' || !path[pos]);
584 while (path[pos] == '/') {
585 pos++;
586 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200587 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200588 return bus;
589 }
590
591 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100592 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
593 assert(0);
594 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200595 }
596 pos += len;
597 dev = qbus_find_dev(bus, elem);
598 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100599 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100600 if (!monitor_cur_is_qmp()) {
601 qbus_list_dev(bus);
602 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200603 return NULL;
604 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100605
606 assert(path[pos] == '/' || !path[pos]);
607 while (path[pos] == '/') {
608 pos++;
609 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200610 if (path[pos] == '\0') {
611 /* last specified element is a device. If it has exactly
612 * one child bus accept it nevertheless */
613 switch (dev->num_child_bus) {
614 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100615 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200616 return NULL;
617 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000618 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200619 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100620 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100621 if (!monitor_cur_is_qmp()) {
622 qbus_list_bus(dev);
623 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200624 return NULL;
625 }
626 }
627
628 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100629 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
630 assert(0);
631 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200632 }
633 pos += len;
634 bus = qbus_find_bus(dev, elem);
635 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100636 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100637 if (!monitor_cur_is_qmp()) {
638 qbus_list_bus(dev);
639 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200640 return NULL;
641 }
642 }
643}
644
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200645void qbus_create_inplace(BusState *bus, BusInfo *info,
646 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100647{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200648 char *buf;
649 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100650
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200651 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100652 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200653
654 if (name) {
655 /* use supplied name */
656 bus->name = qemu_strdup(name);
657 } else if (parent && parent->id) {
658 /* parent device has id -> use it for bus name */
659 len = strlen(parent->id) + 16;
660 buf = qemu_malloc(len);
661 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
662 bus->name = buf;
663 } else {
664 /* no id -> use lowercase bus type for bus name */
665 len = strlen(info->name) + 16;
666 buf = qemu_malloc(len);
667 len = snprintf(buf, len, "%s.%d", info->name,
668 parent ? parent->num_child_bus : 0);
669 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200670 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200671 bus->name = buf;
672 }
673
Blue Swirl72cf2d42009-09-12 07:36:22 +0000674 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100675 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000676 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200677 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100678 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200679
680}
681
682BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
683{
684 BusState *bus;
685
686 bus = qemu_mallocz(info->size);
687 bus->qdev_allocated = 1;
688 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100689 return bus;
690}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100691
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200692void qbus_free(BusState *bus)
693{
694 DeviceState *dev;
695
696 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
697 qdev_free(dev);
698 }
699 if (bus->parent) {
700 QLIST_REMOVE(bus, sibling);
701 bus->parent->num_child_bus--;
702 }
703 if (bus->qdev_allocated) {
704 qemu_free(bus);
705 }
706}
707
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100708#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
709static void qbus_print(Monitor *mon, BusState *bus, int indent);
710
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200711static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
712 const char *prefix, int indent)
713{
714 char buf[64];
715
716 if (!props)
717 return;
718 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100719 /*
720 * TODO Properties without a print method are just for dirty
721 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
722 * marked for removal. The test props->info->print should be
723 * removed along with it.
724 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200725 if (props->info->print) {
726 props->info->print(dev, props, buf, sizeof(buf));
727 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
728 }
729 props++;
730 }
731}
732
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100733static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
734{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100735 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200736 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
737 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100738 indent += 2;
739 if (dev->num_gpio_in) {
740 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
741 }
742 if (dev->num_gpio_out) {
743 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
744 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200745 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
746 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200747 if (dev->parent_bus->info->print_dev)
748 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000749 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100750 qbus_print(mon, child, indent);
751 }
752}
753
754static void qbus_print(Monitor *mon, BusState *bus, int indent)
755{
756 struct DeviceState *dev;
757
758 qdev_printf("bus: %s\n", bus->name);
759 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200760 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000761 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100762 qdev_print(mon, dev, indent);
763 }
764}
765#undef qdev_printf
766
767void do_info_qtree(Monitor *mon)
768{
769 if (main_system_bus)
770 qbus_print(mon, main_system_bus, 0);
771}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200772
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200773void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200774{
775 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200776
777 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100778 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200779 }
780}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200781
Markus Armbruster8bc27242010-02-10 20:52:01 +0100782/**
783 * do_device_add(): Add a device
784 *
785 * Argument qdict contains
786 * - "driver": the name of the new device's driver
787 * - "bus": the device's parent bus (device tree path)
788 * - "id": the device's ID (must be unique)
789 * - device properties
790 *
791 * Example:
792 *
793 * { "driver": "usb-net", "id": "eth1", "netdev": "netdev1" }
794 */
795int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200796{
797 QemuOpts *opts;
798
Markus Armbrusterc7e4e8c2010-02-10 20:47:28 +0100799 opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100800 if (!opts) {
801 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100802 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100803 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
804 qemu_opts_del(opts);
805 return 0;
806 }
807 if (!qdev_device_add(opts)) {
808 qemu_opts_del(opts);
809 return -1;
810 }
811 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200812}
813
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100814int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200815{
816 const char *id = qdict_get_str(qdict, "id");
817 DeviceState *dev;
818
819 dev = qdev_find_recursive(main_system_bus, id);
820 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100821 qerror_report(QERR_DEVICE_NOT_FOUND, id);
822 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200823 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100824 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200825}