blob: 92ccc8d660facd9d32d3edb0bbcbdb76c5a6d6f6 [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"
Blue Swirl24463332010-08-24 15:22:24 +000032#include "blockdev.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 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +020097 dev->instance_id_alias = -1;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +020098 dev->state = DEV_STATE_CREATED;
Paul Brookaae94602009-05-14 22:35:06 +010099 return dev;
100}
101
Markus Armbruster0c175422010-02-19 19:12:18 +0100102/* Create a new device. This only initializes the device state structure
103 and allows properties to be set. qdev_init should be called to
104 initialize the actual device emulation. */
105DeviceState *qdev_create(BusState *bus, const char *name)
106{
107 DeviceInfo *info;
108
109 if (!bus) {
110 if (!main_system_bus) {
111 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
112 }
113 bus = main_system_bus;
114 }
115
116 info = qdev_find_info(bus->info, name);
117 if (!info) {
118 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
119 }
120
121 return qdev_create_from_info(bus, info);
122}
123
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100124static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200125{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100126 error_printf("name \"%s\", bus %s",
127 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200128 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100129 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200130 }
131 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100132 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200133 }
134 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100135 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200136 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100137 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200138}
139
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200140static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200141{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200142 DeviceState *dev = opaque;
143
144 if (strcmp(name, "driver") == 0)
145 return 0;
146 if (strcmp(name, "bus") == 0)
147 return 0;
148
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100149 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200150 return -1;
151 }
152 return 0;
153}
154
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100155int qdev_device_help(QemuOpts *opts)
156{
157 const char *driver;
158 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100159 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100160
161 driver = qemu_opt_get(opts, "driver");
162 if (driver && !strcmp(driver, "?")) {
163 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100164 if (info->no_user) {
165 continue; /* not available, don't show */
166 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100167 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100168 }
169 return 1;
170 }
171
Markus Armbruster08350cf2010-01-29 19:49:00 +0100172 if (!qemu_opt_get(opts, "?")) {
173 return 0;
174 }
175
176 info = qdev_find_info(NULL, driver);
177 if (!info) {
178 return 0;
179 }
180
181 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100182 /*
183 * TODO Properties without a parser are just for dirty hacks.
184 * qdev_prop_ptr is the only such PropertyInfo. It's marked
185 * for removal. This conditional should be removed along with
186 * it.
187 */
188 if (!prop->info->parse) {
189 continue; /* no way to set it, don't show */
190 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100191 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100192 }
193 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100194}
195
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200196DeviceState *qdev_device_add(QemuOpts *opts)
197{
198 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200199 DeviceInfo *info;
200 DeviceState *qdev;
201 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200202
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200203 driver = qemu_opt_get(opts, "driver");
204 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100205 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200206 return NULL;
207 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200208
209 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200210 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100211 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100212 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100213 error_printf_unless_qmp("Try with argument '?' for a list.\n");
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 Armbrusterac8dae62010-02-19 18:09:33 +0100221 if (!bus) {
222 return NULL;
223 }
224 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100225 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
226 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100227 return NULL;
228 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200229 } else {
230 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100231 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100232 qerror_report(QERR_NO_BUS_FOR_DEVICE,
233 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100234 return NULL;
235 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200236 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200237 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100238 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200239 return NULL;
240 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200241
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200242 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100243 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200244 id = qemu_opts_id(opts);
245 if (id) {
246 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200247 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200248 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
249 qdev_free(qdev);
250 return NULL;
251 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200252 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100253 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200254 return NULL;
255 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200256 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200257 return qdev;
258}
259
Paul Brookaae94602009-05-14 22:35:06 +0100260/* Initialize a device. Device properties should be set before calling
261 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200262 calling this function.
263 On failure, destroy the device and return negative value.
264 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200265int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100266{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200267 int rc;
268
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200269 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200270 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200271 if (rc < 0) {
272 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200273 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200274 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200275 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600276 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200277 dev->instance_id_alias,
278 dev->alias_required_for_version);
279 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200280 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200281 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100282}
283
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200284void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
285 int required_for_version)
286{
287 assert(dev->state == DEV_STATE_CREATED);
288 dev->instance_id_alias = alias_id;
289 dev->alias_required_for_version = required_for_version;
290}
291
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200292int qdev_unplug(DeviceState *dev)
293{
294 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100295 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200296 return -1;
297 }
Amit Shah593831d2009-11-02 14:56:41 +0530298 assert(dev->info->unplug != NULL);
299
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200300 return dev->info->unplug(dev);
301}
302
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900303static int qdev_reset_one(DeviceState *dev, void *opaque)
304{
305 if (dev->info->reset) {
306 dev->info->reset(dev);
307 }
308
309 return 0;
310}
311
312BusState *sysbus_get_default(void)
313{
314 return main_system_bus;
315}
316
317void qbus_reset_all(BusState *bus)
318{
319 qbus_walk_children(bus, qdev_reset_one, NULL, NULL);
320}
321
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200322/* can be used as ->unplug() callback for the simple cases */
323int qdev_simple_unplug_cb(DeviceState *dev)
324{
325 /* just zap it */
326 qdev_free(dev);
327 return 0;
328}
329
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200330/* Like qdev_init(), but terminate program via hw_error() instead of
331 returning an error value. This is okay during machine creation.
332 Don't use for hotplug, because there callers need to recover from
333 failure. Exception: if you know the device's init() callback can't
334 fail, then qdev_init_nofail() can't fail either, and is therefore
335 usable even then. But relying on the device implementation that
336 way is somewhat unclean, and best avoided. */
337void qdev_init_nofail(DeviceState *dev)
338{
339 DeviceInfo *info = dev->info;
340
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200341 if (qdev_init(dev) < 0) {
342 error_report("Initialization of device %s failed\n", info->name);
343 exit(1);
344 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200345}
346
Paul Brook02e2da42009-05-23 00:05:19 +0100347/* Unlink device from bus and free the structure. */
348void qdev_free(DeviceState *dev)
349{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200350 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200351 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200352
353 if (dev->state == DEV_STATE_INITIALIZED) {
354 while (dev->num_child_bus) {
355 bus = QLIST_FIRST(&dev->child_bus);
356 qbus_free(bus);
357 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200358 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600359 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200360 if (dev->info->exit)
361 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200362 if (dev->opts)
363 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200364 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000365 QLIST_REMOVE(dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200366 for (prop = dev->info->props; prop && prop->name; prop++) {
367 if (prop->info->free) {
368 prop->info->free(dev, prop);
369 }
370 }
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200371 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100372}
373
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200374void qdev_machine_creation_done(void)
375{
376 /*
377 * ok, initial machine setup is done, starting from now we can
378 * only create hotpluggable devices
379 */
380 qdev_hotplug = 1;
381}
382
Paul Brookaae94602009-05-14 22:35:06 +0100383/* Get a character (serial) device interface. */
384CharDriverState *qdev_init_chardev(DeviceState *dev)
385{
386 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530387
388 /* FIXME: This function needs to go away: use chardev properties! */
389 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100390}
391
Paul Brook02e2da42009-05-23 00:05:19 +0100392BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100393{
Paul Brook02e2da42009-05-23 00:05:19 +0100394 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100395}
396
Paul Brookaae94602009-05-14 22:35:06 +0100397void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
398{
399 assert(dev->num_gpio_in == 0);
400 dev->num_gpio_in = n;
401 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
402}
403
404void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
405{
406 assert(dev->num_gpio_out == 0);
407 dev->num_gpio_out = n;
408 dev->gpio_out = pins;
409}
410
411qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
412{
413 assert(n >= 0 && n < dev->num_gpio_in);
414 return dev->gpio_in[n];
415}
416
417void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
418{
419 assert(n >= 0 && n < dev->num_gpio_out);
420 dev->gpio_out[n] = pin;
421}
422
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200423void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
424{
425 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
426 if (nd->vlan)
427 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
428 if (nd->netdev)
429 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530430 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200431 qdev_prop_exists(dev, "vectors")) {
432 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
433 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200434}
435
Paul Brookaae94602009-05-14 22:35:06 +0100436static int next_block_unit[IF_COUNT];
437
438/* Get a block device. This should only be used for single-drive devices
439 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
440 appropriate bus. */
441BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
442{
443 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200444 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100445
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200446 dinfo = drive_get(type, 0, unit);
447 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100448}
Paul Brook4d6ae672009-05-14 22:35:06 +0100449
Paul Brook02e2da42009-05-23 00:05:19 +0100450BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100451{
Paul Brook02e2da42009-05-23 00:05:19 +0100452 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100453
Blue Swirl72cf2d42009-09-12 07:36:22 +0000454 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100455 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100456 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100457 }
458 }
459 return NULL;
460}
461
Anthony Liguori81699d82010-11-19 18:55:58 +0900462int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
463 qbus_walkerfn *busfn, void *opaque)
464{
465 DeviceState *dev;
466 int err;
467
468 if (busfn) {
469 err = busfn(bus, opaque);
470 if (err) {
471 return err;
472 }
473 }
474
475 QLIST_FOREACH(dev, &bus->children, sibling) {
476 err = qdev_walk_children(dev, devfn, busfn, opaque);
477 if (err < 0) {
478 return err;
479 }
480 }
481
482 return 0;
483}
484
485int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
486 qbus_walkerfn *busfn, void *opaque)
487{
488 BusState *bus;
489 int err;
490
491 if (devfn) {
492 err = devfn(dev, opaque);
493 if (err) {
494 return err;
495 }
496 }
497
498 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
499 err = qbus_walk_children(bus, devfn, busfn, opaque);
500 if (err < 0) {
501 return err;
502 }
503 }
504
505 return 0;
506}
507
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200508static BusState *qbus_find_recursive(BusState *bus, const char *name,
509 const BusInfo *info)
510{
511 DeviceState *dev;
512 BusState *child, *ret;
513 int match = 1;
514
515 if (name && (strcmp(bus->name, name) != 0)) {
516 match = 0;
517 }
518 if (info && (bus->info != info)) {
519 match = 0;
520 }
521 if (match) {
522 return bus;
523 }
524
Blue Swirl72cf2d42009-09-12 07:36:22 +0000525 QLIST_FOREACH(dev, &bus->children, sibling) {
526 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200527 ret = qbus_find_recursive(child, name, info);
528 if (ret) {
529 return ret;
530 }
531 }
532 }
533 return NULL;
534}
535
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200536static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
537{
538 DeviceState *dev, *ret;
539 BusState *child;
540
541 QLIST_FOREACH(dev, &bus->children, sibling) {
542 if (dev->id && strcmp(dev->id, id) == 0)
543 return dev;
544 QLIST_FOREACH(child, &dev->child_bus, sibling) {
545 ret = qdev_find_recursive(child, id);
546 if (ret) {
547 return ret;
548 }
549 }
550 }
551 return NULL;
552}
553
Markus Armbruster53db16b2010-02-18 18:55:59 +0100554static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200555{
556 BusState *child;
557 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200558
Markus Armbruster53db16b2010-02-18 18:55:59 +0100559 error_printf("child busses at \"%s\":",
560 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000561 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100562 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200563 sep = ", ";
564 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100565 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200566}
567
Markus Armbruster53db16b2010-02-18 18:55:59 +0100568static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200569{
570 DeviceState *dev;
571 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200572
Markus Armbruster53db16b2010-02-18 18:55:59 +0100573 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000574 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100575 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200576 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100577 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200578 sep = ", ";
579 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100580 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200581}
582
583static BusState *qbus_find_bus(DeviceState *dev, char *elem)
584{
585 BusState *child;
586
Blue Swirl72cf2d42009-09-12 07:36:22 +0000587 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200588 if (strcmp(child->name, elem) == 0) {
589 return child;
590 }
591 }
592 return NULL;
593}
594
595static DeviceState *qbus_find_dev(BusState *bus, char *elem)
596{
597 DeviceState *dev;
598
599 /*
600 * try to match in order:
601 * (1) instance id, if present
602 * (2) driver name
603 * (3) driver alias, if present
604 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000605 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200606 if (dev->id && strcmp(dev->id, elem) == 0) {
607 return dev;
608 }
609 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000610 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200611 if (strcmp(dev->info->name, elem) == 0) {
612 return dev;
613 }
614 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000615 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200616 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
617 return dev;
618 }
619 }
620 return NULL;
621}
622
623static BusState *qbus_find(const char *path)
624{
625 DeviceState *dev;
626 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100627 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200628 int pos, len;
629
630 /* find start element */
631 if (path[0] == '/') {
632 bus = main_system_bus;
633 pos = 0;
634 } else {
635 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100636 assert(!path[0]);
637 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200638 }
639 bus = qbus_find_recursive(main_system_bus, elem, NULL);
640 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100641 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200642 return NULL;
643 }
644 pos = len;
645 }
646
647 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100648 assert(path[pos] == '/' || !path[pos]);
649 while (path[pos] == '/') {
650 pos++;
651 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200652 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200653 return bus;
654 }
655
656 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100657 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
658 assert(0);
659 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200660 }
661 pos += len;
662 dev = qbus_find_dev(bus, elem);
663 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100664 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100665 if (!monitor_cur_is_qmp()) {
666 qbus_list_dev(bus);
667 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200668 return NULL;
669 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100670
671 assert(path[pos] == '/' || !path[pos]);
672 while (path[pos] == '/') {
673 pos++;
674 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200675 if (path[pos] == '\0') {
676 /* last specified element is a device. If it has exactly
677 * one child bus accept it nevertheless */
678 switch (dev->num_child_bus) {
679 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100680 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200681 return NULL;
682 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000683 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200684 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100685 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100686 if (!monitor_cur_is_qmp()) {
687 qbus_list_bus(dev);
688 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200689 return NULL;
690 }
691 }
692
693 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100694 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
695 assert(0);
696 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200697 }
698 pos += len;
699 bus = qbus_find_bus(dev, elem);
700 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100701 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100702 if (!monitor_cur_is_qmp()) {
703 qbus_list_bus(dev);
704 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200705 return NULL;
706 }
707 }
708}
709
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200710void qbus_create_inplace(BusState *bus, BusInfo *info,
711 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100712{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200713 char *buf;
714 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100715
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200716 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100717 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200718
719 if (name) {
720 /* use supplied name */
721 bus->name = qemu_strdup(name);
722 } else if (parent && parent->id) {
723 /* parent device has id -> use it for bus name */
724 len = strlen(parent->id) + 16;
725 buf = qemu_malloc(len);
726 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
727 bus->name = buf;
728 } else {
729 /* no id -> use lowercase bus type for bus name */
730 len = strlen(info->name) + 16;
731 buf = qemu_malloc(len);
732 len = snprintf(buf, len, "%s.%d", info->name,
733 parent ? parent->num_child_bus : 0);
734 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200735 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200736 bus->name = buf;
737 }
738
Blue Swirl72cf2d42009-09-12 07:36:22 +0000739 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100740 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000741 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200742 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100743 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200744
745}
746
747BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
748{
749 BusState *bus;
750
751 bus = qemu_mallocz(info->size);
752 bus->qdev_allocated = 1;
753 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100754 return bus;
755}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100756
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200757void qbus_free(BusState *bus)
758{
759 DeviceState *dev;
760
761 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
762 qdev_free(dev);
763 }
764 if (bus->parent) {
765 QLIST_REMOVE(bus, sibling);
766 bus->parent->num_child_bus--;
767 }
Isaku Yamahatae163ae72010-05-27 14:35:58 +0900768 qemu_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200769 if (bus->qdev_allocated) {
770 qemu_free(bus);
771 }
772}
773
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100774#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
775static void qbus_print(Monitor *mon, BusState *bus, int indent);
776
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200777static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
778 const char *prefix, int indent)
779{
780 char buf[64];
781
782 if (!props)
783 return;
784 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100785 /*
786 * TODO Properties without a print method are just for dirty
787 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
788 * marked for removal. The test props->info->print should be
789 * removed along with it.
790 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200791 if (props->info->print) {
792 props->info->print(dev, props, buf, sizeof(buf));
793 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
794 }
795 props++;
796 }
797}
798
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100799static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
800{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100801 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200802 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
803 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100804 indent += 2;
805 if (dev->num_gpio_in) {
806 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
807 }
808 if (dev->num_gpio_out) {
809 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
810 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200811 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
812 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200813 if (dev->parent_bus->info->print_dev)
814 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000815 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100816 qbus_print(mon, child, indent);
817 }
818}
819
820static void qbus_print(Monitor *mon, BusState *bus, int indent)
821{
822 struct DeviceState *dev;
823
824 qdev_printf("bus: %s\n", bus->name);
825 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200826 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000827 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100828 qdev_print(mon, dev, indent);
829 }
830}
831#undef qdev_printf
832
833void do_info_qtree(Monitor *mon)
834{
835 if (main_system_bus)
836 qbus_print(mon, main_system_bus, 0);
837}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200838
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200839void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200840{
841 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200842
843 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100844 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200845 }
846}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200847
Markus Armbruster8bc27242010-02-10 20:52:01 +0100848int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200849{
850 QemuOpts *opts;
851
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200852 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100853 if (!opts) {
854 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100855 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100856 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
857 qemu_opts_del(opts);
858 return 0;
859 }
860 if (!qdev_device_add(opts)) {
861 qemu_opts_del(opts);
862 return -1;
863 }
864 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200865}
866
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100867int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200868{
869 const char *id = qdict_get_str(qdict, "id");
870 DeviceState *dev;
871
872 dev = qdev_find_recursive(main_system_bus, id);
873 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100874 qerror_report(QERR_DEVICE_NOT_FOUND, id);
875 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200876 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100877 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200878}