blob: 46081694492888bcf796e60bc2b2939944a21759 [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"
Luiz Capitulino3ced9f72009-11-18 23:05:33 -020032#include "qerror.h"
Paul Brookaae94602009-05-14 22:35:06 +010033
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020034static int qdev_hotplug = 0;
35
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020036/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000037static BusState *main_system_bus;
Paul Brook4d6ae672009-05-14 22:35:06 +010038
Gerd Hoffmann0958b4c2009-10-26 15:56:45 +010039DeviceInfo *device_info_list;
Paul Brookaae94602009-05-14 22:35:06 +010040
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020041static BusState *qbus_find_recursive(BusState *bus, const char *name,
42 const BusInfo *info);
43static BusState *qbus_find(const char *path);
44
Paul Brookaae94602009-05-14 22:35:06 +010045/* Register a new device type. */
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020046void qdev_register(DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010047{
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020048 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020049 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010050
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020051 info->next = device_info_list;
52 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010053}
54
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020055static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
56{
57 DeviceInfo *info;
58
Gerd Hoffmann3320e562009-07-15 13:43:33 +020059 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020060 for (info = device_info_list; info != NULL; info = info->next) {
61 if (bus_info && info->bus_info != bus_info)
62 continue;
63 if (strcmp(info->name, name) != 0)
64 continue;
65 return info;
66 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +020067
68 /* failing that check the aliases */
69 for (info = device_info_list; info != NULL; info = info->next) {
70 if (bus_info && info->bus_info != bus_info)
71 continue;
72 if (!info->alias)
73 continue;
74 if (strcmp(info->alias, name) != 0)
75 continue;
76 return info;
77 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020078 return NULL;
79}
80
Markus Armbruster0c175422010-02-19 19:12:18 +010081static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010082{
Paul Brookaae94602009-05-14 22:35:06 +010083 DeviceState *dev;
84
Markus Armbruster0c175422010-02-19 19:12:18 +010085 assert(bus->info == info->bus_info);
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020086 dev = qemu_mallocz(info->size);
87 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +010088 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020089 qdev_prop_set_defaults(dev, dev->info->props);
90 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010091 qdev_prop_set_globals(dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +000092 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020093 if (qdev_hotplug) {
94 assert(bus->allow_hotplug);
95 dev->hotplugged = 1;
96 }
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) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100149 error_report("can't set property \"%s\" to \"%s\" for \"%s\"",
150 name, value, dev->info->name);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200151 return -1;
152 }
153 return 0;
154}
155
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100156int qdev_device_help(QemuOpts *opts)
157{
158 const char *driver;
159 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100160 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100161
162 driver = qemu_opt_get(opts, "driver");
163 if (driver && !strcmp(driver, "?")) {
164 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100165 if (info->no_user) {
166 continue; /* not available, don't show */
167 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100168 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100169 }
170 return 1;
171 }
172
Markus Armbruster08350cf2010-01-29 19:49:00 +0100173 if (!qemu_opt_get(opts, "?")) {
174 return 0;
175 }
176
177 info = qdev_find_info(NULL, driver);
178 if (!info) {
179 return 0;
180 }
181
182 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100183 /*
184 * TODO Properties without a parser are just for dirty hacks.
185 * qdev_prop_ptr is the only such PropertyInfo. It's marked
186 * for removal. This conditional should be removed along with
187 * it.
188 */
189 if (!prop->info->parse) {
190 continue; /* no way to set it, don't show */
191 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100192 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100193 }
194 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100195}
196
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200197DeviceState *qdev_device_add(QemuOpts *opts)
198{
199 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200200 DeviceInfo *info;
201 DeviceState *qdev;
202 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200203
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200204 driver = qemu_opt_get(opts, "driver");
205 if (!driver) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100206 error_report("-device: no driver specified");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200207 return NULL;
208 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200209
210 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200211 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100212 if (!info || info->no_user) {
Markus Armbrusterab5b0272010-03-02 18:15:09 +0100213 qerror_report(QERR_DEVICE_NOT_FOUND, driver);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200214 return NULL;
215 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200216
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200217 /* find bus */
218 path = qemu_opt_get(opts, "bus");
219 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200220 bus = qbus_find(path);
Markus Armbruster327867b2010-02-19 19:08:45 +0100221 if (bus && bus->info != info->bus_info) {
222 error_report("Device '%s' can't go on a %s bus",
223 driver, bus->info->name);
224 return NULL;
225 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200226 } else {
227 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200228 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200229 if (!bus) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100230 error_report("Did not find %s bus for %s",
231 path ? path : info->bus_info->name, info->name);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200232 return NULL;
Gerd Hoffmann75570082009-08-31 14:23:58 +0200233 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200234 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100235 error_report("Bus %s does not support hotplugging",
236 bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200237 return NULL;
238 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200239
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200240 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100241 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200242 id = qemu_opts_id(opts);
243 if (id) {
244 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200245 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200246 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
247 qdev_free(qdev);
248 return NULL;
249 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200250 if (qdev_init(qdev) < 0) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100251 error_report("Error initializing device %s", driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200252 return NULL;
253 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200254 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200255 return qdev;
256}
257
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300258static void qdev_reset(void *opaque)
259{
260 DeviceState *dev = opaque;
261 if (dev->info->reset)
262 dev->info->reset(dev);
263}
264
Paul Brookaae94602009-05-14 22:35:06 +0100265/* Initialize a device. Device properties should be set before calling
266 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200267 calling this function.
268 On failure, destroy the device and return negative value.
269 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200270int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100271{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200272 int rc;
273
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200274 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200275 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200276 if (rc < 0) {
277 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200278 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200279 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300280 qemu_register_reset(qdev_reset, dev);
Gerd Hoffmann391a0792009-09-01 09:56:14 +0200281 if (dev->info->vmsd)
282 vmstate_register(-1, dev->info->vmsd, dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200283 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200284 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100285}
286
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200287int qdev_unplug(DeviceState *dev)
288{
289 if (!dev->parent_bus->allow_hotplug) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100290 error_report("Bus %s does not support hotplugging",
291 dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200292 return -1;
293 }
Amit Shah593831d2009-11-02 14:56:41 +0530294 assert(dev->info->unplug != NULL);
295
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200296 return dev->info->unplug(dev);
297}
298
299/* can be used as ->unplug() callback for the simple cases */
300int qdev_simple_unplug_cb(DeviceState *dev)
301{
302 /* just zap it */
303 qdev_free(dev);
304 return 0;
305}
306
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200307/* Like qdev_init(), but terminate program via hw_error() instead of
308 returning an error value. This is okay during machine creation.
309 Don't use for hotplug, because there callers need to recover from
310 failure. Exception: if you know the device's init() callback can't
311 fail, then qdev_init_nofail() can't fail either, and is therefore
312 usable even then. But relying on the device implementation that
313 way is somewhat unclean, and best avoided. */
314void qdev_init_nofail(DeviceState *dev)
315{
316 DeviceInfo *info = dev->info;
317
318 if (qdev_init(dev) < 0)
319 hw_error("Initialization of device %s failed\n", info->name);
320}
321
Paul Brook02e2da42009-05-23 00:05:19 +0100322/* Unlink device from bus and free the structure. */
323void qdev_free(DeviceState *dev)
324{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200325 BusState *bus;
326
327 if (dev->state == DEV_STATE_INITIALIZED) {
328 while (dev->num_child_bus) {
329 bus = QLIST_FIRST(&dev->child_bus);
330 qbus_free(bus);
331 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200332 if (dev->info->vmsd)
333 vmstate_unregister(dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200334 if (dev->info->exit)
335 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200336 if (dev->opts)
337 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200338 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300339 qemu_unregister_reset(qdev_reset, dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000340 QLIST_REMOVE(dev, sibling);
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200341 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100342}
343
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200344void qdev_machine_creation_done(void)
345{
346 /*
347 * ok, initial machine setup is done, starting from now we can
348 * only create hotpluggable devices
349 */
350 qdev_hotplug = 1;
351}
352
Paul Brookaae94602009-05-14 22:35:06 +0100353/* Get a character (serial) device interface. */
354CharDriverState *qdev_init_chardev(DeviceState *dev)
355{
356 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530357
358 /* FIXME: This function needs to go away: use chardev properties! */
359 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100360}
361
Paul Brook02e2da42009-05-23 00:05:19 +0100362BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100363{
Paul Brook02e2da42009-05-23 00:05:19 +0100364 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100365}
366
Paul Brookaae94602009-05-14 22:35:06 +0100367void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
368{
369 assert(dev->num_gpio_in == 0);
370 dev->num_gpio_in = n;
371 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
372}
373
374void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
375{
376 assert(dev->num_gpio_out == 0);
377 dev->num_gpio_out = n;
378 dev->gpio_out = pins;
379}
380
381qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
382{
383 assert(n >= 0 && n < dev->num_gpio_in);
384 return dev->gpio_in[n];
385}
386
387void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
388{
389 assert(n >= 0 && n < dev->num_gpio_out);
390 dev->gpio_out[n] = pin;
391}
392
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200393void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
394{
395 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
396 if (nd->vlan)
397 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
398 if (nd->netdev)
399 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530400 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200401 qdev_prop_exists(dev, "vectors")) {
402 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
403 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200404}
405
Paul Brookaae94602009-05-14 22:35:06 +0100406static int next_block_unit[IF_COUNT];
407
408/* Get a block device. This should only be used for single-drive devices
409 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
410 appropriate bus. */
411BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
412{
413 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200414 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100415
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200416 dinfo = drive_get(type, 0, unit);
417 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100418}
Paul Brook4d6ae672009-05-14 22:35:06 +0100419
Paul Brook02e2da42009-05-23 00:05:19 +0100420BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100421{
Paul Brook02e2da42009-05-23 00:05:19 +0100422 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100423
Blue Swirl72cf2d42009-09-12 07:36:22 +0000424 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100425 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100426 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100427 }
428 }
429 return NULL;
430}
431
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200432static BusState *qbus_find_recursive(BusState *bus, const char *name,
433 const BusInfo *info)
434{
435 DeviceState *dev;
436 BusState *child, *ret;
437 int match = 1;
438
439 if (name && (strcmp(bus->name, name) != 0)) {
440 match = 0;
441 }
442 if (info && (bus->info != info)) {
443 match = 0;
444 }
445 if (match) {
446 return bus;
447 }
448
Blue Swirl72cf2d42009-09-12 07:36:22 +0000449 QLIST_FOREACH(dev, &bus->children, sibling) {
450 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200451 ret = qbus_find_recursive(child, name, info);
452 if (ret) {
453 return ret;
454 }
455 }
456 }
457 return NULL;
458}
459
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200460static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
461{
462 DeviceState *dev, *ret;
463 BusState *child;
464
465 QLIST_FOREACH(dev, &bus->children, sibling) {
466 if (dev->id && strcmp(dev->id, id) == 0)
467 return dev;
468 QLIST_FOREACH(child, &dev->child_bus, sibling) {
469 ret = qdev_find_recursive(child, id);
470 if (ret) {
471 return ret;
472 }
473 }
474 }
475 return NULL;
476}
477
Markus Armbruster53db16b2010-02-18 18:55:59 +0100478static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200479{
480 BusState *child;
481 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200482
Markus Armbruster53db16b2010-02-18 18:55:59 +0100483 error_printf("child busses at \"%s\":",
484 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000485 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100486 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200487 sep = ", ";
488 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100489 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200490}
491
Markus Armbruster53db16b2010-02-18 18:55:59 +0100492static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200493{
494 DeviceState *dev;
495 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200496
Markus Armbruster53db16b2010-02-18 18:55:59 +0100497 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000498 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100499 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200500 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100501 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200502 sep = ", ";
503 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100504 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200505}
506
507static BusState *qbus_find_bus(DeviceState *dev, char *elem)
508{
509 BusState *child;
510
Blue Swirl72cf2d42009-09-12 07:36:22 +0000511 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200512 if (strcmp(child->name, elem) == 0) {
513 return child;
514 }
515 }
516 return NULL;
517}
518
519static DeviceState *qbus_find_dev(BusState *bus, char *elem)
520{
521 DeviceState *dev;
522
523 /*
524 * try to match in order:
525 * (1) instance id, if present
526 * (2) driver name
527 * (3) driver alias, if present
528 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000529 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200530 if (dev->id && strcmp(dev->id, elem) == 0) {
531 return dev;
532 }
533 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000534 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200535 if (strcmp(dev->info->name, elem) == 0) {
536 return dev;
537 }
538 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000539 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200540 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
541 return dev;
542 }
543 }
544 return NULL;
545}
546
547static BusState *qbus_find(const char *path)
548{
549 DeviceState *dev;
550 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100551 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200552 int pos, len;
553
554 /* find start element */
555 if (path[0] == '/') {
556 bus = main_system_bus;
557 pos = 0;
558 } else {
559 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100560 error_report("path parse error (\"%s\")", path);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200561 return NULL;
562 }
563 bus = qbus_find_recursive(main_system_bus, elem, NULL);
564 if (!bus) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100565 error_report("bus \"%s\" not found", elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200566 return NULL;
567 }
568 pos = len;
569 }
570
571 for (;;) {
572 if (path[pos] == '\0') {
573 /* we are done */
574 return bus;
575 }
576
577 /* find device */
578 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100579 error_report("path parse error (\"%s\" pos %d)", path, pos);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200580 return NULL;
581 }
582 pos += len;
583 dev = qbus_find_dev(bus, elem);
584 if (!dev) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100585 error_report("device \"%s\" not found", elem);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100586 qbus_list_dev(bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200587 return NULL;
588 }
589 if (path[pos] == '\0') {
590 /* last specified element is a device. If it has exactly
591 * one child bus accept it nevertheless */
592 switch (dev->num_child_bus) {
593 case 0:
Markus Armbruster1ecda022010-02-18 17:25:24 +0100594 error_report("device has no child bus (%s)", path);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200595 return NULL;
596 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000597 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200598 default:
Markus Armbruster1ecda022010-02-18 17:25:24 +0100599 error_report("device has multiple child busses (%s)", path);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100600 qbus_list_bus(dev);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200601 return NULL;
602 }
603 }
604
605 /* find bus */
606 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100607 error_report("path parse error (\"%s\" pos %d)", path, pos);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200608 return NULL;
609 }
610 pos += len;
611 bus = qbus_find_bus(dev, elem);
612 if (!bus) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100613 error_report("child bus \"%s\" not found", elem);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100614 qbus_list_bus(dev);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200615 return NULL;
616 }
617 }
618}
619
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200620void qbus_create_inplace(BusState *bus, BusInfo *info,
621 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100622{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200623 char *buf;
624 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100625
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200626 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100627 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200628
629 if (name) {
630 /* use supplied name */
631 bus->name = qemu_strdup(name);
632 } else if (parent && parent->id) {
633 /* parent device has id -> use it for bus name */
634 len = strlen(parent->id) + 16;
635 buf = qemu_malloc(len);
636 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
637 bus->name = buf;
638 } else {
639 /* no id -> use lowercase bus type for bus name */
640 len = strlen(info->name) + 16;
641 buf = qemu_malloc(len);
642 len = snprintf(buf, len, "%s.%d", info->name,
643 parent ? parent->num_child_bus : 0);
644 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200645 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200646 bus->name = buf;
647 }
648
Blue Swirl72cf2d42009-09-12 07:36:22 +0000649 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100650 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000651 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200652 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100653 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200654
655}
656
657BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
658{
659 BusState *bus;
660
661 bus = qemu_mallocz(info->size);
662 bus->qdev_allocated = 1;
663 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100664 return bus;
665}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100666
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200667void qbus_free(BusState *bus)
668{
669 DeviceState *dev;
670
671 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
672 qdev_free(dev);
673 }
674 if (bus->parent) {
675 QLIST_REMOVE(bus, sibling);
676 bus->parent->num_child_bus--;
677 }
678 if (bus->qdev_allocated) {
679 qemu_free(bus);
680 }
681}
682
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100683#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
684static void qbus_print(Monitor *mon, BusState *bus, int indent);
685
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200686static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
687 const char *prefix, int indent)
688{
689 char buf[64];
690
691 if (!props)
692 return;
693 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100694 /*
695 * TODO Properties without a print method are just for dirty
696 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
697 * marked for removal. The test props->info->print should be
698 * removed along with it.
699 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200700 if (props->info->print) {
701 props->info->print(dev, props, buf, sizeof(buf));
702 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
703 }
704 props++;
705 }
706}
707
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100708static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
709{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100710 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200711 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
712 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100713 indent += 2;
714 if (dev->num_gpio_in) {
715 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
716 }
717 if (dev->num_gpio_out) {
718 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
719 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200720 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
721 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200722 if (dev->parent_bus->info->print_dev)
723 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000724 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100725 qbus_print(mon, child, indent);
726 }
727}
728
729static void qbus_print(Monitor *mon, BusState *bus, int indent)
730{
731 struct DeviceState *dev;
732
733 qdev_printf("bus: %s\n", bus->name);
734 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200735 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000736 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100737 qdev_print(mon, dev, indent);
738 }
739}
740#undef qdev_printf
741
742void do_info_qtree(Monitor *mon)
743{
744 if (main_system_bus)
745 qbus_print(mon, main_system_bus, 0);
746}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200747
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200748void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200749{
750 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200751
752 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100753 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200754 }
755}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200756
757void do_device_add(Monitor *mon, const QDict *qdict)
758{
759 QemuOpts *opts;
760
761 opts = qemu_opts_parse(&qemu_device_opts,
762 qdict_get_str(qdict, "config"), "driver");
Kevin Wolf0f853a32010-02-16 13:12:38 +0100763 if (opts) {
764 if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
765 qemu_opts_del(opts);
766 }
767 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200768}
769
770void do_device_del(Monitor *mon, const QDict *qdict)
771{
772 const char *id = qdict_get_str(qdict, "id");
773 DeviceState *dev;
774
775 dev = qdev_find_recursive(main_system_bus, id);
776 if (NULL == dev) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100777 error_report("Device '%s' not found", id);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200778 return;
779 }
780 qdev_unplug(dev);
781}