blob: 27dc8dfe85dc10d26f374758444119968ea3da45 [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) {
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 Armbruster1ecda022010-02-18 17:25:24 +0100204 error_report("-device: no driver specified");
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 Armbrusterab5b0272010-03-02 18:15:09 +0100211 qerror_report(QERR_DEVICE_NOT_FOUND, driver);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200212 return NULL;
213 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200214
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200215 /* find bus */
216 path = qemu_opt_get(opts, "bus");
217 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200218 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100219 if (!bus) {
220 return NULL;
221 }
222 if (bus->info != info->bus_info) {
Markus Armbruster327867b2010-02-19 19:08:45 +0100223 error_report("Device '%s' can't go on a %s bus",
224 driver, bus->info->name);
225 return NULL;
226 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200227 } else {
228 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100229 if (!bus) {
230 error_report("Did not find %s bus for %s",
231 info->bus_info->name, info->name);
232 return NULL;
233 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200234 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200235 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100236 error_report("Bus %s does not support hotplugging",
237 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 Armbruster1ecda022010-02-18 17:25:24 +0100252 error_report("Error initializing device %s", 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);
Gerd Hoffmann391a0792009-09-01 09:56:14 +0200282 if (dev->info->vmsd)
283 vmstate_register(-1, dev->info->vmsd, dev);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200284 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200285 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100286}
287
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200288int qdev_unplug(DeviceState *dev)
289{
290 if (!dev->parent_bus->allow_hotplug) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100291 error_report("Bus %s does not support hotplugging",
292 dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200293 return -1;
294 }
Amit Shah593831d2009-11-02 14:56:41 +0530295 assert(dev->info->unplug != NULL);
296
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200297 return dev->info->unplug(dev);
298}
299
300/* can be used as ->unplug() callback for the simple cases */
301int qdev_simple_unplug_cb(DeviceState *dev)
302{
303 /* just zap it */
304 qdev_free(dev);
305 return 0;
306}
307
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200308/* Like qdev_init(), but terminate program via hw_error() instead of
309 returning an error value. This is okay during machine creation.
310 Don't use for hotplug, because there callers need to recover from
311 failure. Exception: if you know the device's init() callback can't
312 fail, then qdev_init_nofail() can't fail either, and is therefore
313 usable even then. But relying on the device implementation that
314 way is somewhat unclean, and best avoided. */
315void qdev_init_nofail(DeviceState *dev)
316{
317 DeviceInfo *info = dev->info;
318
319 if (qdev_init(dev) < 0)
320 hw_error("Initialization of device %s failed\n", info->name);
321}
322
Paul Brook02e2da42009-05-23 00:05:19 +0100323/* Unlink device from bus and free the structure. */
324void qdev_free(DeviceState *dev)
325{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200326 BusState *bus;
327
328 if (dev->state == DEV_STATE_INITIALIZED) {
329 while (dev->num_child_bus) {
330 bus = QLIST_FIRST(&dev->child_bus);
331 qbus_free(bus);
332 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200333 if (dev->info->vmsd)
334 vmstate_unregister(dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200335 if (dev->info->exit)
336 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200337 if (dev->opts)
338 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200339 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300340 qemu_unregister_reset(qdev_reset, dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000341 QLIST_REMOVE(dev, sibling);
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200342 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100343}
344
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200345void qdev_machine_creation_done(void)
346{
347 /*
348 * ok, initial machine setup is done, starting from now we can
349 * only create hotpluggable devices
350 */
351 qdev_hotplug = 1;
352}
353
Paul Brookaae94602009-05-14 22:35:06 +0100354/* Get a character (serial) device interface. */
355CharDriverState *qdev_init_chardev(DeviceState *dev)
356{
357 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530358
359 /* FIXME: This function needs to go away: use chardev properties! */
360 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100361}
362
Paul Brook02e2da42009-05-23 00:05:19 +0100363BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100364{
Paul Brook02e2da42009-05-23 00:05:19 +0100365 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100366}
367
Paul Brookaae94602009-05-14 22:35:06 +0100368void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
369{
370 assert(dev->num_gpio_in == 0);
371 dev->num_gpio_in = n;
372 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
373}
374
375void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
376{
377 assert(dev->num_gpio_out == 0);
378 dev->num_gpio_out = n;
379 dev->gpio_out = pins;
380}
381
382qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
383{
384 assert(n >= 0 && n < dev->num_gpio_in);
385 return dev->gpio_in[n];
386}
387
388void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
389{
390 assert(n >= 0 && n < dev->num_gpio_out);
391 dev->gpio_out[n] = pin;
392}
393
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200394void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
395{
396 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
397 if (nd->vlan)
398 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
399 if (nd->netdev)
400 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530401 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200402 qdev_prop_exists(dev, "vectors")) {
403 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
404 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200405}
406
Paul Brookaae94602009-05-14 22:35:06 +0100407static int next_block_unit[IF_COUNT];
408
409/* Get a block device. This should only be used for single-drive devices
410 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
411 appropriate bus. */
412BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
413{
414 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200415 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100416
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200417 dinfo = drive_get(type, 0, unit);
418 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100419}
Paul Brook4d6ae672009-05-14 22:35:06 +0100420
Paul Brook02e2da42009-05-23 00:05:19 +0100421BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100422{
Paul Brook02e2da42009-05-23 00:05:19 +0100423 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100424
Blue Swirl72cf2d42009-09-12 07:36:22 +0000425 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100426 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100427 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100428 }
429 }
430 return NULL;
431}
432
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200433static BusState *qbus_find_recursive(BusState *bus, const char *name,
434 const BusInfo *info)
435{
436 DeviceState *dev;
437 BusState *child, *ret;
438 int match = 1;
439
440 if (name && (strcmp(bus->name, name) != 0)) {
441 match = 0;
442 }
443 if (info && (bus->info != info)) {
444 match = 0;
445 }
446 if (match) {
447 return bus;
448 }
449
Blue Swirl72cf2d42009-09-12 07:36:22 +0000450 QLIST_FOREACH(dev, &bus->children, sibling) {
451 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200452 ret = qbus_find_recursive(child, name, info);
453 if (ret) {
454 return ret;
455 }
456 }
457 }
458 return NULL;
459}
460
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200461static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
462{
463 DeviceState *dev, *ret;
464 BusState *child;
465
466 QLIST_FOREACH(dev, &bus->children, sibling) {
467 if (dev->id && strcmp(dev->id, id) == 0)
468 return dev;
469 QLIST_FOREACH(child, &dev->child_bus, sibling) {
470 ret = qdev_find_recursive(child, id);
471 if (ret) {
472 return ret;
473 }
474 }
475 }
476 return NULL;
477}
478
Markus Armbruster53db16b2010-02-18 18:55:59 +0100479static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200480{
481 BusState *child;
482 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200483
Markus Armbruster53db16b2010-02-18 18:55:59 +0100484 error_printf("child busses at \"%s\":",
485 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000486 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100487 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200488 sep = ", ";
489 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100490 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200491}
492
Markus Armbruster53db16b2010-02-18 18:55:59 +0100493static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200494{
495 DeviceState *dev;
496 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200497
Markus Armbruster53db16b2010-02-18 18:55:59 +0100498 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000499 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100500 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200501 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100502 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200503 sep = ", ";
504 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100505 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200506}
507
508static BusState *qbus_find_bus(DeviceState *dev, char *elem)
509{
510 BusState *child;
511
Blue Swirl72cf2d42009-09-12 07:36:22 +0000512 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200513 if (strcmp(child->name, elem) == 0) {
514 return child;
515 }
516 }
517 return NULL;
518}
519
520static DeviceState *qbus_find_dev(BusState *bus, char *elem)
521{
522 DeviceState *dev;
523
524 /*
525 * try to match in order:
526 * (1) instance id, if present
527 * (2) driver name
528 * (3) driver alias, if present
529 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000530 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200531 if (dev->id && strcmp(dev->id, elem) == 0) {
532 return dev;
533 }
534 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000535 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200536 if (strcmp(dev->info->name, elem) == 0) {
537 return dev;
538 }
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->info->alias && strcmp(dev->info->alias, elem) == 0) {
542 return dev;
543 }
544 }
545 return NULL;
546}
547
548static BusState *qbus_find(const char *path)
549{
550 DeviceState *dev;
551 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100552 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200553 int pos, len;
554
555 /* find start element */
556 if (path[0] == '/') {
557 bus = main_system_bus;
558 pos = 0;
559 } else {
560 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100561 assert(!path[0]);
562 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200563 }
564 bus = qbus_find_recursive(main_system_bus, elem, NULL);
565 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100566 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200567 return NULL;
568 }
569 pos = len;
570 }
571
572 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100573 assert(path[pos] == '/' || !path[pos]);
574 while (path[pos] == '/') {
575 pos++;
576 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200577 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200578 return bus;
579 }
580
581 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100582 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
583 assert(0);
584 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200585 }
586 pos += len;
587 dev = qbus_find_dev(bus, elem);
588 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100589 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100590 qbus_list_dev(bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200591 return NULL;
592 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100593
594 assert(path[pos] == '/' || !path[pos]);
595 while (path[pos] == '/') {
596 pos++;
597 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200598 if (path[pos] == '\0') {
599 /* last specified element is a device. If it has exactly
600 * one child bus accept it nevertheless */
601 switch (dev->num_child_bus) {
602 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100603 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200604 return NULL;
605 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000606 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200607 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100608 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100609 qbus_list_bus(dev);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200610 return NULL;
611 }
612 }
613
614 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100615 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
616 assert(0);
617 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200618 }
619 pos += len;
620 bus = qbus_find_bus(dev, elem);
621 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100622 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster53db16b2010-02-18 18:55:59 +0100623 qbus_list_bus(dev);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200624 return NULL;
625 }
626 }
627}
628
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200629void qbus_create_inplace(BusState *bus, BusInfo *info,
630 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100631{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200632 char *buf;
633 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100634
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200635 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100636 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200637
638 if (name) {
639 /* use supplied name */
640 bus->name = qemu_strdup(name);
641 } else if (parent && parent->id) {
642 /* parent device has id -> use it for bus name */
643 len = strlen(parent->id) + 16;
644 buf = qemu_malloc(len);
645 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
646 bus->name = buf;
647 } else {
648 /* no id -> use lowercase bus type for bus name */
649 len = strlen(info->name) + 16;
650 buf = qemu_malloc(len);
651 len = snprintf(buf, len, "%s.%d", info->name,
652 parent ? parent->num_child_bus : 0);
653 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200654 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200655 bus->name = buf;
656 }
657
Blue Swirl72cf2d42009-09-12 07:36:22 +0000658 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100659 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000660 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200661 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100662 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200663
664}
665
666BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
667{
668 BusState *bus;
669
670 bus = qemu_mallocz(info->size);
671 bus->qdev_allocated = 1;
672 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100673 return bus;
674}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100675
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200676void qbus_free(BusState *bus)
677{
678 DeviceState *dev;
679
680 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
681 qdev_free(dev);
682 }
683 if (bus->parent) {
684 QLIST_REMOVE(bus, sibling);
685 bus->parent->num_child_bus--;
686 }
687 if (bus->qdev_allocated) {
688 qemu_free(bus);
689 }
690}
691
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100692#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
693static void qbus_print(Monitor *mon, BusState *bus, int indent);
694
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200695static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
696 const char *prefix, int indent)
697{
698 char buf[64];
699
700 if (!props)
701 return;
702 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100703 /*
704 * TODO Properties without a print method are just for dirty
705 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
706 * marked for removal. The test props->info->print should be
707 * removed along with it.
708 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200709 if (props->info->print) {
710 props->info->print(dev, props, buf, sizeof(buf));
711 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
712 }
713 props++;
714 }
715}
716
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100717static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
718{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100719 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200720 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
721 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100722 indent += 2;
723 if (dev->num_gpio_in) {
724 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
725 }
726 if (dev->num_gpio_out) {
727 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
728 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200729 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
730 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200731 if (dev->parent_bus->info->print_dev)
732 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000733 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100734 qbus_print(mon, child, indent);
735 }
736}
737
738static void qbus_print(Monitor *mon, BusState *bus, int indent)
739{
740 struct DeviceState *dev;
741
742 qdev_printf("bus: %s\n", bus->name);
743 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200744 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000745 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100746 qdev_print(mon, dev, indent);
747 }
748}
749#undef qdev_printf
750
751void do_info_qtree(Monitor *mon)
752{
753 if (main_system_bus)
754 qbus_print(mon, main_system_bus, 0);
755}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200756
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200757void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200758{
759 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200760
761 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100762 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200763 }
764}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200765
766void do_device_add(Monitor *mon, const QDict *qdict)
767{
768 QemuOpts *opts;
769
770 opts = qemu_opts_parse(&qemu_device_opts,
771 qdict_get_str(qdict, "config"), "driver");
Kevin Wolf0f853a32010-02-16 13:12:38 +0100772 if (opts) {
773 if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
774 qemu_opts_del(opts);
775 }
776 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200777}
778
779void do_device_del(Monitor *mon, const QDict *qdict)
780{
781 const char *id = qdict_get_str(qdict, "id");
782 DeviceState *dev;
783
784 dev = qdev_find_recursive(main_system_bus, id);
785 if (NULL == dev) {
Markus Armbruster1ecda022010-02-18 17:25:24 +0100786 error_report("Device '%s' not found", id);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200787 return;
788 }
789 qdev_unplug(dev);
790}