blob: 5ca126b49fafd3e5dbf194acbb182f4e0f47839d [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 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +020096 dev->state = DEV_STATE_CREATED;
Paul Brookaae94602009-05-14 22:35:06 +010097 return dev;
98}
99
Markus Armbruster0c175422010-02-19 19:12:18 +0100100/* Create a new device. This only initializes the device state structure
101 and allows properties to be set. qdev_init should be called to
102 initialize the actual device emulation. */
103DeviceState *qdev_create(BusState *bus, const char *name)
104{
105 DeviceInfo *info;
106
107 if (!bus) {
108 if (!main_system_bus) {
109 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
110 }
111 bus = main_system_bus;
112 }
113
114 info = qdev_find_info(bus->info, name);
115 if (!info) {
116 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
117 }
118
119 return qdev_create_from_info(bus, info);
120}
121
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100122static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200123{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100124 error_printf("name \"%s\", bus %s",
125 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200126 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100127 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200128 }
129 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100130 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200131 }
132 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100133 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200134 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100135 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200136}
137
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200138static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200139{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200140 DeviceState *dev = opaque;
141
142 if (strcmp(name, "driver") == 0)
143 return 0;
144 if (strcmp(name, "bus") == 0)
145 return 0;
146
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100147 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200148 return -1;
149 }
150 return 0;
151}
152
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100153int qdev_device_help(QemuOpts *opts)
154{
155 const char *driver;
156 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100157 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100158
159 driver = qemu_opt_get(opts, "driver");
160 if (driver && !strcmp(driver, "?")) {
161 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100162 if (info->no_user) {
163 continue; /* not available, don't show */
164 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100165 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100166 }
167 return 1;
168 }
169
Markus Armbruster08350cf2010-01-29 19:49:00 +0100170 if (!qemu_opt_get(opts, "?")) {
171 return 0;
172 }
173
174 info = qdev_find_info(NULL, driver);
175 if (!info) {
176 return 0;
177 }
178
179 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100180 /*
181 * TODO Properties without a parser are just for dirty hacks.
182 * qdev_prop_ptr is the only such PropertyInfo. It's marked
183 * for removal. This conditional should be removed along with
184 * it.
185 */
186 if (!prop->info->parse) {
187 continue; /* no way to set it, don't show */
188 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100189 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100190 }
191 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100192}
193
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200194DeviceState *qdev_device_add(QemuOpts *opts)
195{
196 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200197 DeviceInfo *info;
198 DeviceState *qdev;
199 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200200
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200201 driver = qemu_opt_get(opts, "driver");
202 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100203 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200204 return NULL;
205 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200206
207 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200208 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100209 if (!info || info->no_user) {
Markus Armbruster02042762010-02-19 14:17:34 +0100210 qerror_report(QERR_INVALID_PARAMETER, "driver");
211 error_printf_unless_qmp("Try with argument '?' for a list.\n");
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 Armbruster02042762010-02-19 14:17:34 +0100223 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
224 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100225 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) {
Markus Armbruster02042762010-02-19 14:17:34 +0100230 qerror_report(QERR_NO_BUS_FOR_DEVICE,
231 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100232 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 Armbruster02042762010-02-19 14:17:34 +0100236 qerror_report(QERR_BUS_NO_HOTPLUG, 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 Armbruster02042762010-02-19 14:17:34 +0100251 qerror_report(QERR_DEVICE_INIT_FAILED, 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 Armbrustercc601cb2010-03-22 11:38:13 +0100290 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200291 return -1;
292 }
Amit Shah593831d2009-11-02 14:56:41 +0530293 assert(dev->info->unplug != NULL);
294
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200295 return dev->info->unplug(dev);
296}
297
298/* can be used as ->unplug() callback for the simple cases */
299int qdev_simple_unplug_cb(DeviceState *dev)
300{
301 /* just zap it */
302 qdev_free(dev);
303 return 0;
304}
305
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200306/* Like qdev_init(), but terminate program via hw_error() instead of
307 returning an error value. This is okay during machine creation.
308 Don't use for hotplug, because there callers need to recover from
309 failure. Exception: if you know the device's init() callback can't
310 fail, then qdev_init_nofail() can't fail either, and is therefore
311 usable even then. But relying on the device implementation that
312 way is somewhat unclean, and best avoided. */
313void qdev_init_nofail(DeviceState *dev)
314{
315 DeviceInfo *info = dev->info;
316
317 if (qdev_init(dev) < 0)
318 hw_error("Initialization of device %s failed\n", info->name);
319}
320
Paul Brook02e2da42009-05-23 00:05:19 +0100321/* Unlink device from bus and free the structure. */
322void qdev_free(DeviceState *dev)
323{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200324 BusState *bus;
325
326 if (dev->state == DEV_STATE_INITIALIZED) {
327 while (dev->num_child_bus) {
328 bus = QLIST_FIRST(&dev->child_bus);
329 qbus_free(bus);
330 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200331 if (dev->info->vmsd)
332 vmstate_unregister(dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200333 if (dev->info->exit)
334 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200335 if (dev->opts)
336 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200337 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300338 qemu_unregister_reset(qdev_reset, dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000339 QLIST_REMOVE(dev, sibling);
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200340 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100341}
342
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200343void qdev_machine_creation_done(void)
344{
345 /*
346 * ok, initial machine setup is done, starting from now we can
347 * only create hotpluggable devices
348 */
349 qdev_hotplug = 1;
350}
351
Paul Brookaae94602009-05-14 22:35:06 +0100352/* Get a character (serial) device interface. */
353CharDriverState *qdev_init_chardev(DeviceState *dev)
354{
355 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530356
357 /* FIXME: This function needs to go away: use chardev properties! */
358 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100359}
360
Paul Brook02e2da42009-05-23 00:05:19 +0100361BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100362{
Paul Brook02e2da42009-05-23 00:05:19 +0100363 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100364}
365
Paul Brookaae94602009-05-14 22:35:06 +0100366void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
367{
368 assert(dev->num_gpio_in == 0);
369 dev->num_gpio_in = n;
370 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
371}
372
373void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
374{
375 assert(dev->num_gpio_out == 0);
376 dev->num_gpio_out = n;
377 dev->gpio_out = pins;
378}
379
380qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
381{
382 assert(n >= 0 && n < dev->num_gpio_in);
383 return dev->gpio_in[n];
384}
385
386void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
387{
388 assert(n >= 0 && n < dev->num_gpio_out);
389 dev->gpio_out[n] = pin;
390}
391
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200392void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
393{
394 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
395 if (nd->vlan)
396 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
397 if (nd->netdev)
398 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530399 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200400 qdev_prop_exists(dev, "vectors")) {
401 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
402 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200403}
404
Paul Brookaae94602009-05-14 22:35:06 +0100405static int next_block_unit[IF_COUNT];
406
407/* Get a block device. This should only be used for single-drive devices
408 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
409 appropriate bus. */
410BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
411{
412 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200413 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100414
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200415 dinfo = drive_get(type, 0, unit);
416 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100417}
Paul Brook4d6ae672009-05-14 22:35:06 +0100418
Paul Brook02e2da42009-05-23 00:05:19 +0100419BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100420{
Paul Brook02e2da42009-05-23 00:05:19 +0100421 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100422
Blue Swirl72cf2d42009-09-12 07:36:22 +0000423 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100424 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100425 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100426 }
427 }
428 return NULL;
429}
430
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200431static BusState *qbus_find_recursive(BusState *bus, const char *name,
432 const BusInfo *info)
433{
434 DeviceState *dev;
435 BusState *child, *ret;
436 int match = 1;
437
438 if (name && (strcmp(bus->name, name) != 0)) {
439 match = 0;
440 }
441 if (info && (bus->info != info)) {
442 match = 0;
443 }
444 if (match) {
445 return bus;
446 }
447
Blue Swirl72cf2d42009-09-12 07:36:22 +0000448 QLIST_FOREACH(dev, &bus->children, sibling) {
449 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200450 ret = qbus_find_recursive(child, name, info);
451 if (ret) {
452 return ret;
453 }
454 }
455 }
456 return NULL;
457}
458
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200459static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
460{
461 DeviceState *dev, *ret;
462 BusState *child;
463
464 QLIST_FOREACH(dev, &bus->children, sibling) {
465 if (dev->id && strcmp(dev->id, id) == 0)
466 return dev;
467 QLIST_FOREACH(child, &dev->child_bus, sibling) {
468 ret = qdev_find_recursive(child, id);
469 if (ret) {
470 return ret;
471 }
472 }
473 }
474 return NULL;
475}
476
Markus Armbruster53db16b2010-02-18 18:55:59 +0100477static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200478{
479 BusState *child;
480 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200481
Markus Armbruster53db16b2010-02-18 18:55:59 +0100482 error_printf("child busses at \"%s\":",
483 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000484 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100485 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200486 sep = ", ";
487 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100488 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200489}
490
Markus Armbruster53db16b2010-02-18 18:55:59 +0100491static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200492{
493 DeviceState *dev;
494 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200495
Markus Armbruster53db16b2010-02-18 18:55:59 +0100496 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000497 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100498 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200499 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100500 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200501 sep = ", ";
502 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100503 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200504}
505
506static BusState *qbus_find_bus(DeviceState *dev, char *elem)
507{
508 BusState *child;
509
Blue Swirl72cf2d42009-09-12 07:36:22 +0000510 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200511 if (strcmp(child->name, elem) == 0) {
512 return child;
513 }
514 }
515 return NULL;
516}
517
518static DeviceState *qbus_find_dev(BusState *bus, char *elem)
519{
520 DeviceState *dev;
521
522 /*
523 * try to match in order:
524 * (1) instance id, if present
525 * (2) driver name
526 * (3) driver alias, if present
527 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000528 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200529 if (dev->id && strcmp(dev->id, elem) == 0) {
530 return dev;
531 }
532 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000533 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200534 if (strcmp(dev->info->name, elem) == 0) {
535 return dev;
536 }
537 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000538 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200539 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
540 return dev;
541 }
542 }
543 return NULL;
544}
545
546static BusState *qbus_find(const char *path)
547{
548 DeviceState *dev;
549 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100550 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200551 int pos, len;
552
553 /* find start element */
554 if (path[0] == '/') {
555 bus = main_system_bus;
556 pos = 0;
557 } else {
558 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100559 assert(!path[0]);
560 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200561 }
562 bus = qbus_find_recursive(main_system_bus, elem, NULL);
563 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100564 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200565 return NULL;
566 }
567 pos = len;
568 }
569
570 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100571 assert(path[pos] == '/' || !path[pos]);
572 while (path[pos] == '/') {
573 pos++;
574 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200575 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200576 return bus;
577 }
578
579 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100580 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
581 assert(0);
582 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200583 }
584 pos += len;
585 dev = qbus_find_dev(bus, elem);
586 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100587 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100588 if (!monitor_cur_is_qmp()) {
589 qbus_list_dev(bus);
590 }
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 Armbruster8bc27242010-02-10 20:52:01 +0100609 if (!monitor_cur_is_qmp()) {
610 qbus_list_bus(dev);
611 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200612 return NULL;
613 }
614 }
615
616 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100617 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
618 assert(0);
619 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200620 }
621 pos += len;
622 bus = qbus_find_bus(dev, elem);
623 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100624 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100625 if (!monitor_cur_is_qmp()) {
626 qbus_list_bus(dev);
627 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200628 return NULL;
629 }
630 }
631}
632
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200633void qbus_create_inplace(BusState *bus, BusInfo *info,
634 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100635{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200636 char *buf;
637 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100638
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200639 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100640 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200641
642 if (name) {
643 /* use supplied name */
644 bus->name = qemu_strdup(name);
645 } else if (parent && parent->id) {
646 /* parent device has id -> use it for bus name */
647 len = strlen(parent->id) + 16;
648 buf = qemu_malloc(len);
649 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
650 bus->name = buf;
651 } else {
652 /* no id -> use lowercase bus type for bus name */
653 len = strlen(info->name) + 16;
654 buf = qemu_malloc(len);
655 len = snprintf(buf, len, "%s.%d", info->name,
656 parent ? parent->num_child_bus : 0);
657 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200658 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200659 bus->name = buf;
660 }
661
Blue Swirl72cf2d42009-09-12 07:36:22 +0000662 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100663 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000664 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200665 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100666 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200667
668}
669
670BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
671{
672 BusState *bus;
673
674 bus = qemu_mallocz(info->size);
675 bus->qdev_allocated = 1;
676 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100677 return bus;
678}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100679
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200680void qbus_free(BusState *bus)
681{
682 DeviceState *dev;
683
684 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
685 qdev_free(dev);
686 }
687 if (bus->parent) {
688 QLIST_REMOVE(bus, sibling);
689 bus->parent->num_child_bus--;
690 }
691 if (bus->qdev_allocated) {
692 qemu_free(bus);
693 }
694}
695
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100696#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
697static void qbus_print(Monitor *mon, BusState *bus, int indent);
698
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200699static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
700 const char *prefix, int indent)
701{
702 char buf[64];
703
704 if (!props)
705 return;
706 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100707 /*
708 * TODO Properties without a print method are just for dirty
709 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
710 * marked for removal. The test props->info->print should be
711 * removed along with it.
712 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200713 if (props->info->print) {
714 props->info->print(dev, props, buf, sizeof(buf));
715 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
716 }
717 props++;
718 }
719}
720
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100721static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
722{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100723 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200724 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
725 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100726 indent += 2;
727 if (dev->num_gpio_in) {
728 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
729 }
730 if (dev->num_gpio_out) {
731 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
732 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200733 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
734 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200735 if (dev->parent_bus->info->print_dev)
736 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000737 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100738 qbus_print(mon, child, indent);
739 }
740}
741
742static void qbus_print(Monitor *mon, BusState *bus, int indent)
743{
744 struct DeviceState *dev;
745
746 qdev_printf("bus: %s\n", bus->name);
747 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200748 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000749 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100750 qdev_print(mon, dev, indent);
751 }
752}
753#undef qdev_printf
754
755void do_info_qtree(Monitor *mon)
756{
757 if (main_system_bus)
758 qbus_print(mon, main_system_bus, 0);
759}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200760
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200761void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200762{
763 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200764
765 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100766 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200767 }
768}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200769
Markus Armbruster8bc27242010-02-10 20:52:01 +0100770/**
771 * do_device_add(): Add a device
772 *
773 * Argument qdict contains
774 * - "driver": the name of the new device's driver
775 * - "bus": the device's parent bus (device tree path)
776 * - "id": the device's ID (must be unique)
777 * - device properties
778 *
779 * Example:
780 *
781 * { "driver": "usb-net", "id": "eth1", "netdev": "netdev1" }
782 */
783int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200784{
785 QemuOpts *opts;
786
Markus Armbrusterc7e4e8c2010-02-10 20:47:28 +0100787 opts = qemu_opts_from_qdict(&qemu_device_opts, qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100788 if (!opts) {
789 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100790 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100791 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
792 qemu_opts_del(opts);
793 return 0;
794 }
795 if (!qdev_device_add(opts)) {
796 qemu_opts_del(opts);
797 return -1;
798 }
799 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200800}
801
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100802int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200803{
804 const char *id = qdict_get_str(qdict, "id");
805 DeviceState *dev;
806
807 dev = qdev_find_recursive(main_system_bus, id);
808 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100809 qerror_report(QERR_DEVICE_NOT_FOUND, id);
810 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200811 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100812 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200813}