blob: b76da078088a8b141a031fe8f0aa8a15768f7e03 [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
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900317static int qbus_reset_one(BusState *bus, void *opaque)
318{
319 if (bus->info->reset) {
320 return bus->info->reset(bus);
321 }
322 return 0;
323}
324
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900325void qbus_reset_all(BusState *bus)
326{
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900327 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900328}
329
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200330/* can be used as ->unplug() callback for the simple cases */
331int qdev_simple_unplug_cb(DeviceState *dev)
332{
333 /* just zap it */
334 qdev_free(dev);
335 return 0;
336}
337
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200338/* Like qdev_init(), but terminate program via hw_error() instead of
339 returning an error value. This is okay during machine creation.
340 Don't use for hotplug, because there callers need to recover from
341 failure. Exception: if you know the device's init() callback can't
342 fail, then qdev_init_nofail() can't fail either, and is therefore
343 usable even then. But relying on the device implementation that
344 way is somewhat unclean, and best avoided. */
345void qdev_init_nofail(DeviceState *dev)
346{
347 DeviceInfo *info = dev->info;
348
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200349 if (qdev_init(dev) < 0) {
350 error_report("Initialization of device %s failed\n", info->name);
351 exit(1);
352 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200353}
354
Paul Brook02e2da42009-05-23 00:05:19 +0100355/* Unlink device from bus and free the structure. */
356void qdev_free(DeviceState *dev)
357{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200358 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200359 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200360
361 if (dev->state == DEV_STATE_INITIALIZED) {
362 while (dev->num_child_bus) {
363 bus = QLIST_FIRST(&dev->child_bus);
364 qbus_free(bus);
365 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200366 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600367 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200368 if (dev->info->exit)
369 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200370 if (dev->opts)
371 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200372 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000373 QLIST_REMOVE(dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200374 for (prop = dev->info->props; prop && prop->name; prop++) {
375 if (prop->info->free) {
376 prop->info->free(dev, prop);
377 }
378 }
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200379 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100380}
381
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200382void qdev_machine_creation_done(void)
383{
384 /*
385 * ok, initial machine setup is done, starting from now we can
386 * only create hotpluggable devices
387 */
388 qdev_hotplug = 1;
389}
390
Paul Brookaae94602009-05-14 22:35:06 +0100391/* Get a character (serial) device interface. */
392CharDriverState *qdev_init_chardev(DeviceState *dev)
393{
394 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530395
396 /* FIXME: This function needs to go away: use chardev properties! */
397 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100398}
399
Paul Brook02e2da42009-05-23 00:05:19 +0100400BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100401{
Paul Brook02e2da42009-05-23 00:05:19 +0100402 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100403}
404
Paul Brookaae94602009-05-14 22:35:06 +0100405void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
406{
407 assert(dev->num_gpio_in == 0);
408 dev->num_gpio_in = n;
409 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
410}
411
412void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
413{
414 assert(dev->num_gpio_out == 0);
415 dev->num_gpio_out = n;
416 dev->gpio_out = pins;
417}
418
419qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
420{
421 assert(n >= 0 && n < dev->num_gpio_in);
422 return dev->gpio_in[n];
423}
424
425void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
426{
427 assert(n >= 0 && n < dev->num_gpio_out);
428 dev->gpio_out[n] = pin;
429}
430
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200431void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
432{
433 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
434 if (nd->vlan)
435 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
436 if (nd->netdev)
437 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530438 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200439 qdev_prop_exists(dev, "vectors")) {
440 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
441 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200442}
443
Paul Brookaae94602009-05-14 22:35:06 +0100444static int next_block_unit[IF_COUNT];
445
446/* Get a block device. This should only be used for single-drive devices
447 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
448 appropriate bus. */
449BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
450{
451 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200452 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100453
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200454 dinfo = drive_get(type, 0, unit);
455 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100456}
Paul Brook4d6ae672009-05-14 22:35:06 +0100457
Paul Brook02e2da42009-05-23 00:05:19 +0100458BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100459{
Paul Brook02e2da42009-05-23 00:05:19 +0100460 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100461
Blue Swirl72cf2d42009-09-12 07:36:22 +0000462 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100463 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100464 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100465 }
466 }
467 return NULL;
468}
469
Anthony Liguori81699d82010-11-19 18:55:58 +0900470int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
471 qbus_walkerfn *busfn, void *opaque)
472{
473 DeviceState *dev;
474 int err;
475
476 if (busfn) {
477 err = busfn(bus, opaque);
478 if (err) {
479 return err;
480 }
481 }
482
483 QLIST_FOREACH(dev, &bus->children, sibling) {
484 err = qdev_walk_children(dev, devfn, busfn, opaque);
485 if (err < 0) {
486 return err;
487 }
488 }
489
490 return 0;
491}
492
493int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
494 qbus_walkerfn *busfn, void *opaque)
495{
496 BusState *bus;
497 int err;
498
499 if (devfn) {
500 err = devfn(dev, opaque);
501 if (err) {
502 return err;
503 }
504 }
505
506 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
507 err = qbus_walk_children(bus, devfn, busfn, opaque);
508 if (err < 0) {
509 return err;
510 }
511 }
512
513 return 0;
514}
515
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200516static BusState *qbus_find_recursive(BusState *bus, const char *name,
517 const BusInfo *info)
518{
519 DeviceState *dev;
520 BusState *child, *ret;
521 int match = 1;
522
523 if (name && (strcmp(bus->name, name) != 0)) {
524 match = 0;
525 }
526 if (info && (bus->info != info)) {
527 match = 0;
528 }
529 if (match) {
530 return bus;
531 }
532
Blue Swirl72cf2d42009-09-12 07:36:22 +0000533 QLIST_FOREACH(dev, &bus->children, sibling) {
534 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200535 ret = qbus_find_recursive(child, name, info);
536 if (ret) {
537 return ret;
538 }
539 }
540 }
541 return NULL;
542}
543
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200544static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
545{
546 DeviceState *dev, *ret;
547 BusState *child;
548
549 QLIST_FOREACH(dev, &bus->children, sibling) {
550 if (dev->id && strcmp(dev->id, id) == 0)
551 return dev;
552 QLIST_FOREACH(child, &dev->child_bus, sibling) {
553 ret = qdev_find_recursive(child, id);
554 if (ret) {
555 return ret;
556 }
557 }
558 }
559 return NULL;
560}
561
Markus Armbruster53db16b2010-02-18 18:55:59 +0100562static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200563{
564 BusState *child;
565 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200566
Markus Armbruster53db16b2010-02-18 18:55:59 +0100567 error_printf("child busses at \"%s\":",
568 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000569 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100570 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200571 sep = ", ";
572 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100573 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200574}
575
Markus Armbruster53db16b2010-02-18 18:55:59 +0100576static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200577{
578 DeviceState *dev;
579 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200580
Markus Armbruster53db16b2010-02-18 18:55:59 +0100581 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000582 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100583 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200584 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100585 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200586 sep = ", ";
587 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100588 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200589}
590
591static BusState *qbus_find_bus(DeviceState *dev, char *elem)
592{
593 BusState *child;
594
Blue Swirl72cf2d42009-09-12 07:36:22 +0000595 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200596 if (strcmp(child->name, elem) == 0) {
597 return child;
598 }
599 }
600 return NULL;
601}
602
603static DeviceState *qbus_find_dev(BusState *bus, char *elem)
604{
605 DeviceState *dev;
606
607 /*
608 * try to match in order:
609 * (1) instance id, if present
610 * (2) driver name
611 * (3) driver alias, if present
612 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000613 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200614 if (dev->id && strcmp(dev->id, elem) == 0) {
615 return dev;
616 }
617 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000618 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200619 if (strcmp(dev->info->name, elem) == 0) {
620 return dev;
621 }
622 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000623 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200624 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
625 return dev;
626 }
627 }
628 return NULL;
629}
630
631static BusState *qbus_find(const char *path)
632{
633 DeviceState *dev;
634 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100635 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200636 int pos, len;
637
638 /* find start element */
639 if (path[0] == '/') {
640 bus = main_system_bus;
641 pos = 0;
642 } else {
643 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100644 assert(!path[0]);
645 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200646 }
647 bus = qbus_find_recursive(main_system_bus, elem, NULL);
648 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100649 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200650 return NULL;
651 }
652 pos = len;
653 }
654
655 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100656 assert(path[pos] == '/' || !path[pos]);
657 while (path[pos] == '/') {
658 pos++;
659 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200660 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200661 return bus;
662 }
663
664 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100665 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
666 assert(0);
667 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200668 }
669 pos += len;
670 dev = qbus_find_dev(bus, elem);
671 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100672 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100673 if (!monitor_cur_is_qmp()) {
674 qbus_list_dev(bus);
675 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200676 return NULL;
677 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100678
679 assert(path[pos] == '/' || !path[pos]);
680 while (path[pos] == '/') {
681 pos++;
682 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200683 if (path[pos] == '\0') {
684 /* last specified element is a device. If it has exactly
685 * one child bus accept it nevertheless */
686 switch (dev->num_child_bus) {
687 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100688 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200689 return NULL;
690 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000691 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200692 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100693 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100694 if (!monitor_cur_is_qmp()) {
695 qbus_list_bus(dev);
696 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200697 return NULL;
698 }
699 }
700
701 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100702 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
703 assert(0);
704 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200705 }
706 pos += len;
707 bus = qbus_find_bus(dev, elem);
708 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100709 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100710 if (!monitor_cur_is_qmp()) {
711 qbus_list_bus(dev);
712 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200713 return NULL;
714 }
715 }
716}
717
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200718void qbus_create_inplace(BusState *bus, BusInfo *info,
719 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100720{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200721 char *buf;
722 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100723
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200724 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100725 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200726
727 if (name) {
728 /* use supplied name */
729 bus->name = qemu_strdup(name);
730 } else if (parent && parent->id) {
731 /* parent device has id -> use it for bus name */
732 len = strlen(parent->id) + 16;
733 buf = qemu_malloc(len);
734 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
735 bus->name = buf;
736 } else {
737 /* no id -> use lowercase bus type for bus name */
738 len = strlen(info->name) + 16;
739 buf = qemu_malloc(len);
740 len = snprintf(buf, len, "%s.%d", info->name,
741 parent ? parent->num_child_bus : 0);
742 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200743 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200744 bus->name = buf;
745 }
746
Blue Swirl72cf2d42009-09-12 07:36:22 +0000747 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100748 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000749 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200750 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100751 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200752
753}
754
755BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
756{
757 BusState *bus;
758
759 bus = qemu_mallocz(info->size);
760 bus->qdev_allocated = 1;
761 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100762 return bus;
763}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100764
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200765void qbus_free(BusState *bus)
766{
767 DeviceState *dev;
768
769 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
770 qdev_free(dev);
771 }
772 if (bus->parent) {
773 QLIST_REMOVE(bus, sibling);
774 bus->parent->num_child_bus--;
775 }
Isaku Yamahatae163ae72010-05-27 14:35:58 +0900776 qemu_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200777 if (bus->qdev_allocated) {
778 qemu_free(bus);
779 }
780}
781
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100782#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
783static void qbus_print(Monitor *mon, BusState *bus, int indent);
784
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200785static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
786 const char *prefix, int indent)
787{
788 char buf[64];
789
790 if (!props)
791 return;
792 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100793 /*
794 * TODO Properties without a print method are just for dirty
795 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
796 * marked for removal. The test props->info->print should be
797 * removed along with it.
798 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200799 if (props->info->print) {
800 props->info->print(dev, props, buf, sizeof(buf));
801 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
802 }
803 props++;
804 }
805}
806
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100807static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
808{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100809 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200810 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
811 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100812 indent += 2;
813 if (dev->num_gpio_in) {
814 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
815 }
816 if (dev->num_gpio_out) {
817 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
818 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200819 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
820 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200821 if (dev->parent_bus->info->print_dev)
822 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000823 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100824 qbus_print(mon, child, indent);
825 }
826}
827
828static void qbus_print(Monitor *mon, BusState *bus, int indent)
829{
830 struct DeviceState *dev;
831
832 qdev_printf("bus: %s\n", bus->name);
833 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200834 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000835 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100836 qdev_print(mon, dev, indent);
837 }
838}
839#undef qdev_printf
840
841void do_info_qtree(Monitor *mon)
842{
843 if (main_system_bus)
844 qbus_print(mon, main_system_bus, 0);
845}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200846
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200847void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200848{
849 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200850
851 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100852 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200853 }
854}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200855
Markus Armbruster8bc27242010-02-10 20:52:01 +0100856int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200857{
858 QemuOpts *opts;
859
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200860 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100861 if (!opts) {
862 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100863 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100864 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
865 qemu_opts_del(opts);
866 return 0;
867 }
868 if (!qdev_device_add(opts)) {
869 qemu_opts_del(opts);
870 return -1;
871 }
872 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200873}
874
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100875int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200876{
877 const char *id = qdict_get_str(qdict, "id");
878 DeviceState *dev;
879
880 dev = qdev_find_recursive(main_system_bus, id);
881 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100882 qerror_report(QERR_DEVICE_NOT_FOUND, id);
883 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200884 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100885 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200886}