blob: 11d845ac066dd2119eeb022c692cfcbb26d04d01 [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
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300260static void qdev_reset(void *opaque)
261{
262 DeviceState *dev = opaque;
263 if (dev->info->reset)
264 dev->info->reset(dev);
265}
266
Paul Brookaae94602009-05-14 22:35:06 +0100267/* Initialize a device. Device properties should be set before calling
268 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200269 calling this function.
270 On failure, destroy the device and return negative value.
271 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200272int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100273{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200274 int rc;
275
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200276 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200277 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200278 if (rc < 0) {
279 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200280 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200281 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300282 qemu_register_reset(qdev_reset, dev);
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200283 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600284 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200285 dev->instance_id_alias,
286 dev->alias_required_for_version);
287 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200288 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200289 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100290}
291
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200292void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
293 int required_for_version)
294{
295 assert(dev->state == DEV_STATE_CREATED);
296 dev->instance_id_alias = alias_id;
297 dev->alias_required_for_version = required_for_version;
298}
299
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200300int qdev_unplug(DeviceState *dev)
301{
302 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100303 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200304 return -1;
305 }
Amit Shah593831d2009-11-02 14:56:41 +0530306 assert(dev->info->unplug != NULL);
307
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200308 return dev->info->unplug(dev);
309}
310
311/* can be used as ->unplug() callback for the simple cases */
312int qdev_simple_unplug_cb(DeviceState *dev)
313{
314 /* just zap it */
315 qdev_free(dev);
316 return 0;
317}
318
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200319/* Like qdev_init(), but terminate program via hw_error() instead of
320 returning an error value. This is okay during machine creation.
321 Don't use for hotplug, because there callers need to recover from
322 failure. Exception: if you know the device's init() callback can't
323 fail, then qdev_init_nofail() can't fail either, and is therefore
324 usable even then. But relying on the device implementation that
325 way is somewhat unclean, and best avoided. */
326void qdev_init_nofail(DeviceState *dev)
327{
328 DeviceInfo *info = dev->info;
329
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200330 if (qdev_init(dev) < 0) {
331 error_report("Initialization of device %s failed\n", info->name);
332 exit(1);
333 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200334}
335
Paul Brook02e2da42009-05-23 00:05:19 +0100336/* Unlink device from bus and free the structure. */
337void qdev_free(DeviceState *dev)
338{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200339 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200340 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200341
342 if (dev->state == DEV_STATE_INITIALIZED) {
343 while (dev->num_child_bus) {
344 bus = QLIST_FIRST(&dev->child_bus);
345 qbus_free(bus);
346 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200347 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600348 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200349 if (dev->info->exit)
350 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200351 if (dev->opts)
352 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200353 }
Michael S. Tsirkin7f23f812009-09-16 13:40:27 +0300354 qemu_unregister_reset(qdev_reset, dev);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000355 QLIST_REMOVE(dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200356 for (prop = dev->info->props; prop && prop->name; prop++) {
357 if (prop->info->free) {
358 prop->info->free(dev, prop);
359 }
360 }
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200361 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100362}
363
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200364void qdev_machine_creation_done(void)
365{
366 /*
367 * ok, initial machine setup is done, starting from now we can
368 * only create hotpluggable devices
369 */
370 qdev_hotplug = 1;
371}
372
Paul Brookaae94602009-05-14 22:35:06 +0100373/* Get a character (serial) device interface. */
374CharDriverState *qdev_init_chardev(DeviceState *dev)
375{
376 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530377
378 /* FIXME: This function needs to go away: use chardev properties! */
379 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100380}
381
Paul Brook02e2da42009-05-23 00:05:19 +0100382BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100383{
Paul Brook02e2da42009-05-23 00:05:19 +0100384 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100385}
386
Paul Brookaae94602009-05-14 22:35:06 +0100387void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
388{
389 assert(dev->num_gpio_in == 0);
390 dev->num_gpio_in = n;
391 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
392}
393
394void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
395{
396 assert(dev->num_gpio_out == 0);
397 dev->num_gpio_out = n;
398 dev->gpio_out = pins;
399}
400
401qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
402{
403 assert(n >= 0 && n < dev->num_gpio_in);
404 return dev->gpio_in[n];
405}
406
407void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
408{
409 assert(n >= 0 && n < dev->num_gpio_out);
410 dev->gpio_out[n] = pin;
411}
412
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200413void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
414{
415 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
416 if (nd->vlan)
417 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
418 if (nd->netdev)
419 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530420 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200421 qdev_prop_exists(dev, "vectors")) {
422 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
423 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200424}
425
Paul Brookaae94602009-05-14 22:35:06 +0100426static int next_block_unit[IF_COUNT];
427
428/* Get a block device. This should only be used for single-drive devices
429 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
430 appropriate bus. */
431BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
432{
433 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200434 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100435
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200436 dinfo = drive_get(type, 0, unit);
437 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100438}
Paul Brook4d6ae672009-05-14 22:35:06 +0100439
Paul Brook02e2da42009-05-23 00:05:19 +0100440BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100441{
Paul Brook02e2da42009-05-23 00:05:19 +0100442 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100443
Blue Swirl72cf2d42009-09-12 07:36:22 +0000444 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100445 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100446 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100447 }
448 }
449 return NULL;
450}
451
Anthony Liguori81699d82010-11-19 18:55:58 +0900452int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
453 qbus_walkerfn *busfn, void *opaque)
454{
455 DeviceState *dev;
456 int err;
457
458 if (busfn) {
459 err = busfn(bus, opaque);
460 if (err) {
461 return err;
462 }
463 }
464
465 QLIST_FOREACH(dev, &bus->children, sibling) {
466 err = qdev_walk_children(dev, devfn, busfn, opaque);
467 if (err < 0) {
468 return err;
469 }
470 }
471
472 return 0;
473}
474
475int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
476 qbus_walkerfn *busfn, void *opaque)
477{
478 BusState *bus;
479 int err;
480
481 if (devfn) {
482 err = devfn(dev, opaque);
483 if (err) {
484 return err;
485 }
486 }
487
488 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
489 err = qbus_walk_children(bus, devfn, busfn, opaque);
490 if (err < 0) {
491 return err;
492 }
493 }
494
495 return 0;
496}
497
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200498static BusState *qbus_find_recursive(BusState *bus, const char *name,
499 const BusInfo *info)
500{
501 DeviceState *dev;
502 BusState *child, *ret;
503 int match = 1;
504
505 if (name && (strcmp(bus->name, name) != 0)) {
506 match = 0;
507 }
508 if (info && (bus->info != info)) {
509 match = 0;
510 }
511 if (match) {
512 return bus;
513 }
514
Blue Swirl72cf2d42009-09-12 07:36:22 +0000515 QLIST_FOREACH(dev, &bus->children, sibling) {
516 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200517 ret = qbus_find_recursive(child, name, info);
518 if (ret) {
519 return ret;
520 }
521 }
522 }
523 return NULL;
524}
525
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200526static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
527{
528 DeviceState *dev, *ret;
529 BusState *child;
530
531 QLIST_FOREACH(dev, &bus->children, sibling) {
532 if (dev->id && strcmp(dev->id, id) == 0)
533 return dev;
534 QLIST_FOREACH(child, &dev->child_bus, sibling) {
535 ret = qdev_find_recursive(child, id);
536 if (ret) {
537 return ret;
538 }
539 }
540 }
541 return NULL;
542}
543
Markus Armbruster53db16b2010-02-18 18:55:59 +0100544static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200545{
546 BusState *child;
547 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200548
Markus Armbruster53db16b2010-02-18 18:55:59 +0100549 error_printf("child busses at \"%s\":",
550 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000551 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100552 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200553 sep = ", ";
554 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100555 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200556}
557
Markus Armbruster53db16b2010-02-18 18:55:59 +0100558static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200559{
560 DeviceState *dev;
561 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200562
Markus Armbruster53db16b2010-02-18 18:55:59 +0100563 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000564 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100565 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200566 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100567 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200568 sep = ", ";
569 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100570 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200571}
572
573static BusState *qbus_find_bus(DeviceState *dev, char *elem)
574{
575 BusState *child;
576
Blue Swirl72cf2d42009-09-12 07:36:22 +0000577 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200578 if (strcmp(child->name, elem) == 0) {
579 return child;
580 }
581 }
582 return NULL;
583}
584
585static DeviceState *qbus_find_dev(BusState *bus, char *elem)
586{
587 DeviceState *dev;
588
589 /*
590 * try to match in order:
591 * (1) instance id, if present
592 * (2) driver name
593 * (3) driver alias, if present
594 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000595 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200596 if (dev->id && strcmp(dev->id, elem) == 0) {
597 return dev;
598 }
599 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000600 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200601 if (strcmp(dev->info->name, elem) == 0) {
602 return dev;
603 }
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->info->alias && strcmp(dev->info->alias, elem) == 0) {
607 return dev;
608 }
609 }
610 return NULL;
611}
612
613static BusState *qbus_find(const char *path)
614{
615 DeviceState *dev;
616 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100617 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200618 int pos, len;
619
620 /* find start element */
621 if (path[0] == '/') {
622 bus = main_system_bus;
623 pos = 0;
624 } else {
625 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100626 assert(!path[0]);
627 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200628 }
629 bus = qbus_find_recursive(main_system_bus, elem, NULL);
630 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100631 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200632 return NULL;
633 }
634 pos = len;
635 }
636
637 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100638 assert(path[pos] == '/' || !path[pos]);
639 while (path[pos] == '/') {
640 pos++;
641 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200642 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200643 return bus;
644 }
645
646 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100647 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
648 assert(0);
649 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200650 }
651 pos += len;
652 dev = qbus_find_dev(bus, elem);
653 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100654 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100655 if (!monitor_cur_is_qmp()) {
656 qbus_list_dev(bus);
657 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200658 return NULL;
659 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100660
661 assert(path[pos] == '/' || !path[pos]);
662 while (path[pos] == '/') {
663 pos++;
664 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200665 if (path[pos] == '\0') {
666 /* last specified element is a device. If it has exactly
667 * one child bus accept it nevertheless */
668 switch (dev->num_child_bus) {
669 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100670 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200671 return NULL;
672 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000673 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200674 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100675 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100676 if (!monitor_cur_is_qmp()) {
677 qbus_list_bus(dev);
678 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200679 return NULL;
680 }
681 }
682
683 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100684 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
685 assert(0);
686 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200687 }
688 pos += len;
689 bus = qbus_find_bus(dev, elem);
690 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100691 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100692 if (!monitor_cur_is_qmp()) {
693 qbus_list_bus(dev);
694 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200695 return NULL;
696 }
697 }
698}
699
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200700void qbus_create_inplace(BusState *bus, BusInfo *info,
701 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100702{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200703 char *buf;
704 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100705
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200706 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100707 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200708
709 if (name) {
710 /* use supplied name */
711 bus->name = qemu_strdup(name);
712 } else if (parent && parent->id) {
713 /* parent device has id -> use it for bus name */
714 len = strlen(parent->id) + 16;
715 buf = qemu_malloc(len);
716 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
717 bus->name = buf;
718 } else {
719 /* no id -> use lowercase bus type for bus name */
720 len = strlen(info->name) + 16;
721 buf = qemu_malloc(len);
722 len = snprintf(buf, len, "%s.%d", info->name,
723 parent ? parent->num_child_bus : 0);
724 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200725 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200726 bus->name = buf;
727 }
728
Blue Swirl72cf2d42009-09-12 07:36:22 +0000729 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100730 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000731 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200732 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100733 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200734
735}
736
737BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
738{
739 BusState *bus;
740
741 bus = qemu_mallocz(info->size);
742 bus->qdev_allocated = 1;
743 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100744 return bus;
745}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100746
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200747void qbus_free(BusState *bus)
748{
749 DeviceState *dev;
750
751 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
752 qdev_free(dev);
753 }
754 if (bus->parent) {
755 QLIST_REMOVE(bus, sibling);
756 bus->parent->num_child_bus--;
757 }
Isaku Yamahatae163ae72010-05-27 14:35:58 +0900758 qemu_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200759 if (bus->qdev_allocated) {
760 qemu_free(bus);
761 }
762}
763
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100764#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
765static void qbus_print(Monitor *mon, BusState *bus, int indent);
766
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200767static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
768 const char *prefix, int indent)
769{
770 char buf[64];
771
772 if (!props)
773 return;
774 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100775 /*
776 * TODO Properties without a print method are just for dirty
777 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
778 * marked for removal. The test props->info->print should be
779 * removed along with it.
780 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200781 if (props->info->print) {
782 props->info->print(dev, props, buf, sizeof(buf));
783 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
784 }
785 props++;
786 }
787}
788
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100789static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
790{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100791 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200792 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
793 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100794 indent += 2;
795 if (dev->num_gpio_in) {
796 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
797 }
798 if (dev->num_gpio_out) {
799 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
800 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200801 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
802 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200803 if (dev->parent_bus->info->print_dev)
804 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000805 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100806 qbus_print(mon, child, indent);
807 }
808}
809
810static void qbus_print(Monitor *mon, BusState *bus, int indent)
811{
812 struct DeviceState *dev;
813
814 qdev_printf("bus: %s\n", bus->name);
815 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200816 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000817 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100818 qdev_print(mon, dev, indent);
819 }
820}
821#undef qdev_printf
822
823void do_info_qtree(Monitor *mon)
824{
825 if (main_system_bus)
826 qbus_print(mon, main_system_bus, 0);
827}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200828
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200829void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200830{
831 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200832
833 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100834 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200835 }
836}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200837
Markus Armbruster8bc27242010-02-10 20:52:01 +0100838int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200839{
840 QemuOpts *opts;
841
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200842 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100843 if (!opts) {
844 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100845 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100846 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
847 qemu_opts_del(opts);
848 return 0;
849 }
850 if (!qdev_device_add(opts)) {
851 qemu_opts_del(opts);
852 return -1;
853 }
854 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200855}
856
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100857int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200858{
859 const char *id = qdict_get_str(qdict, "id");
860 DeviceState *dev;
861
862 dev = qdev_find_recursive(main_system_bus, id);
863 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100864 qerror_report(QERR_DEVICE_NOT_FOUND, id);
865 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200866 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100867 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200868}