blob: 10e28df7a1804ce28d44a5b6ae33d7b600f71066 [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
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900325void qdev_reset_all(DeviceState *dev)
326{
327 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
328}
329
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900330void qbus_reset_all(BusState *bus)
331{
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900332 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900333}
334
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200335/* can be used as ->unplug() callback for the simple cases */
336int qdev_simple_unplug_cb(DeviceState *dev)
337{
338 /* just zap it */
339 qdev_free(dev);
340 return 0;
341}
342
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200343/* Like qdev_init(), but terminate program via hw_error() instead of
344 returning an error value. This is okay during machine creation.
345 Don't use for hotplug, because there callers need to recover from
346 failure. Exception: if you know the device's init() callback can't
347 fail, then qdev_init_nofail() can't fail either, and is therefore
348 usable even then. But relying on the device implementation that
349 way is somewhat unclean, and best avoided. */
350void qdev_init_nofail(DeviceState *dev)
351{
352 DeviceInfo *info = dev->info;
353
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200354 if (qdev_init(dev) < 0) {
355 error_report("Initialization of device %s failed\n", info->name);
356 exit(1);
357 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200358}
359
Paul Brook02e2da42009-05-23 00:05:19 +0100360/* Unlink device from bus and free the structure. */
361void qdev_free(DeviceState *dev)
362{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200363 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200364 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200365
366 if (dev->state == DEV_STATE_INITIALIZED) {
367 while (dev->num_child_bus) {
368 bus = QLIST_FIRST(&dev->child_bus);
369 qbus_free(bus);
370 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200371 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600372 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200373 if (dev->info->exit)
374 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200375 if (dev->opts)
376 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200377 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000378 QLIST_REMOVE(dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200379 for (prop = dev->info->props; prop && prop->name; prop++) {
380 if (prop->info->free) {
381 prop->info->free(dev, prop);
382 }
383 }
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200384 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100385}
386
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200387void qdev_machine_creation_done(void)
388{
389 /*
390 * ok, initial machine setup is done, starting from now we can
391 * only create hotpluggable devices
392 */
393 qdev_hotplug = 1;
394}
395
Paul Brookaae94602009-05-14 22:35:06 +0100396/* Get a character (serial) device interface. */
397CharDriverState *qdev_init_chardev(DeviceState *dev)
398{
399 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530400
401 /* FIXME: This function needs to go away: use chardev properties! */
402 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100403}
404
Paul Brook02e2da42009-05-23 00:05:19 +0100405BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100406{
Paul Brook02e2da42009-05-23 00:05:19 +0100407 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100408}
409
Paul Brookaae94602009-05-14 22:35:06 +0100410void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
411{
412 assert(dev->num_gpio_in == 0);
413 dev->num_gpio_in = n;
414 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
415}
416
417void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
418{
419 assert(dev->num_gpio_out == 0);
420 dev->num_gpio_out = n;
421 dev->gpio_out = pins;
422}
423
424qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
425{
426 assert(n >= 0 && n < dev->num_gpio_in);
427 return dev->gpio_in[n];
428}
429
430void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
431{
432 assert(n >= 0 && n < dev->num_gpio_out);
433 dev->gpio_out[n] = pin;
434}
435
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200436void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
437{
438 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
439 if (nd->vlan)
440 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
441 if (nd->netdev)
442 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530443 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200444 qdev_prop_exists(dev, "vectors")) {
445 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
446 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200447}
448
Paul Brookaae94602009-05-14 22:35:06 +0100449static int next_block_unit[IF_COUNT];
450
451/* Get a block device. This should only be used for single-drive devices
452 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
453 appropriate bus. */
454BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
455{
456 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200457 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100458
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200459 dinfo = drive_get(type, 0, unit);
460 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100461}
Paul Brook4d6ae672009-05-14 22:35:06 +0100462
Paul Brook02e2da42009-05-23 00:05:19 +0100463BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100464{
Paul Brook02e2da42009-05-23 00:05:19 +0100465 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100466
Blue Swirl72cf2d42009-09-12 07:36:22 +0000467 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100468 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100469 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100470 }
471 }
472 return NULL;
473}
474
Anthony Liguori81699d82010-11-19 18:55:58 +0900475int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
476 qbus_walkerfn *busfn, void *opaque)
477{
478 DeviceState *dev;
479 int err;
480
481 if (busfn) {
482 err = busfn(bus, opaque);
483 if (err) {
484 return err;
485 }
486 }
487
488 QLIST_FOREACH(dev, &bus->children, sibling) {
489 err = qdev_walk_children(dev, devfn, busfn, opaque);
490 if (err < 0) {
491 return err;
492 }
493 }
494
495 return 0;
496}
497
498int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
499 qbus_walkerfn *busfn, void *opaque)
500{
501 BusState *bus;
502 int err;
503
504 if (devfn) {
505 err = devfn(dev, opaque);
506 if (err) {
507 return err;
508 }
509 }
510
511 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
512 err = qbus_walk_children(bus, devfn, busfn, opaque);
513 if (err < 0) {
514 return err;
515 }
516 }
517
518 return 0;
519}
520
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200521static BusState *qbus_find_recursive(BusState *bus, const char *name,
522 const BusInfo *info)
523{
524 DeviceState *dev;
525 BusState *child, *ret;
526 int match = 1;
527
528 if (name && (strcmp(bus->name, name) != 0)) {
529 match = 0;
530 }
531 if (info && (bus->info != info)) {
532 match = 0;
533 }
534 if (match) {
535 return bus;
536 }
537
Blue Swirl72cf2d42009-09-12 07:36:22 +0000538 QLIST_FOREACH(dev, &bus->children, sibling) {
539 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200540 ret = qbus_find_recursive(child, name, info);
541 if (ret) {
542 return ret;
543 }
544 }
545 }
546 return NULL;
547}
548
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200549static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
550{
551 DeviceState *dev, *ret;
552 BusState *child;
553
554 QLIST_FOREACH(dev, &bus->children, sibling) {
555 if (dev->id && strcmp(dev->id, id) == 0)
556 return dev;
557 QLIST_FOREACH(child, &dev->child_bus, sibling) {
558 ret = qdev_find_recursive(child, id);
559 if (ret) {
560 return ret;
561 }
562 }
563 }
564 return NULL;
565}
566
Markus Armbruster53db16b2010-02-18 18:55:59 +0100567static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200568{
569 BusState *child;
570 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200571
Markus Armbruster53db16b2010-02-18 18:55:59 +0100572 error_printf("child busses at \"%s\":",
573 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000574 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100575 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200576 sep = ", ";
577 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100578 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200579}
580
Markus Armbruster53db16b2010-02-18 18:55:59 +0100581static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200582{
583 DeviceState *dev;
584 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200585
Markus Armbruster53db16b2010-02-18 18:55:59 +0100586 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000587 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100588 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200589 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100590 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200591 sep = ", ";
592 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100593 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200594}
595
596static BusState *qbus_find_bus(DeviceState *dev, char *elem)
597{
598 BusState *child;
599
Blue Swirl72cf2d42009-09-12 07:36:22 +0000600 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200601 if (strcmp(child->name, elem) == 0) {
602 return child;
603 }
604 }
605 return NULL;
606}
607
608static DeviceState *qbus_find_dev(BusState *bus, char *elem)
609{
610 DeviceState *dev;
611
612 /*
613 * try to match in order:
614 * (1) instance id, if present
615 * (2) driver name
616 * (3) driver alias, if present
617 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000618 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200619 if (dev->id && strcmp(dev->id, 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 (strcmp(dev->info->name, elem) == 0) {
625 return dev;
626 }
627 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000628 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200629 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
630 return dev;
631 }
632 }
633 return NULL;
634}
635
636static BusState *qbus_find(const char *path)
637{
638 DeviceState *dev;
639 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100640 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200641 int pos, len;
642
643 /* find start element */
644 if (path[0] == '/') {
645 bus = main_system_bus;
646 pos = 0;
647 } else {
648 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100649 assert(!path[0]);
650 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200651 }
652 bus = qbus_find_recursive(main_system_bus, elem, NULL);
653 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100654 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200655 return NULL;
656 }
657 pos = len;
658 }
659
660 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100661 assert(path[pos] == '/' || !path[pos]);
662 while (path[pos] == '/') {
663 pos++;
664 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200665 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200666 return bus;
667 }
668
669 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100670 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
671 assert(0);
672 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200673 }
674 pos += len;
675 dev = qbus_find_dev(bus, elem);
676 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100677 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100678 if (!monitor_cur_is_qmp()) {
679 qbus_list_dev(bus);
680 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200681 return NULL;
682 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100683
684 assert(path[pos] == '/' || !path[pos]);
685 while (path[pos] == '/') {
686 pos++;
687 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200688 if (path[pos] == '\0') {
689 /* last specified element is a device. If it has exactly
690 * one child bus accept it nevertheless */
691 switch (dev->num_child_bus) {
692 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100693 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200694 return NULL;
695 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000696 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200697 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100698 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100699 if (!monitor_cur_is_qmp()) {
700 qbus_list_bus(dev);
701 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200702 return NULL;
703 }
704 }
705
706 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100707 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
708 assert(0);
709 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200710 }
711 pos += len;
712 bus = qbus_find_bus(dev, elem);
713 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100714 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100715 if (!monitor_cur_is_qmp()) {
716 qbus_list_bus(dev);
717 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200718 return NULL;
719 }
720 }
721}
722
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200723void qbus_create_inplace(BusState *bus, BusInfo *info,
724 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100725{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200726 char *buf;
727 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100728
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200729 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100730 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200731
732 if (name) {
733 /* use supplied name */
734 bus->name = qemu_strdup(name);
735 } else if (parent && parent->id) {
736 /* parent device has id -> use it for bus name */
737 len = strlen(parent->id) + 16;
738 buf = qemu_malloc(len);
739 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
740 bus->name = buf;
741 } else {
742 /* no id -> use lowercase bus type for bus name */
743 len = strlen(info->name) + 16;
744 buf = qemu_malloc(len);
745 len = snprintf(buf, len, "%s.%d", info->name,
746 parent ? parent->num_child_bus : 0);
747 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200748 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200749 bus->name = buf;
750 }
751
Blue Swirl72cf2d42009-09-12 07:36:22 +0000752 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100753 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000754 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200755 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100756 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200757
758}
759
760BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
761{
762 BusState *bus;
763
764 bus = qemu_mallocz(info->size);
765 bus->qdev_allocated = 1;
766 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100767 return bus;
768}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100769
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200770void qbus_free(BusState *bus)
771{
772 DeviceState *dev;
773
774 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
775 qdev_free(dev);
776 }
777 if (bus->parent) {
778 QLIST_REMOVE(bus, sibling);
779 bus->parent->num_child_bus--;
780 }
Isaku Yamahatae163ae72010-05-27 14:35:58 +0900781 qemu_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200782 if (bus->qdev_allocated) {
783 qemu_free(bus);
784 }
785}
786
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100787#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
788static void qbus_print(Monitor *mon, BusState *bus, int indent);
789
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200790static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
791 const char *prefix, int indent)
792{
793 char buf[64];
794
795 if (!props)
796 return;
797 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100798 /*
799 * TODO Properties without a print method are just for dirty
800 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
801 * marked for removal. The test props->info->print should be
802 * removed along with it.
803 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200804 if (props->info->print) {
805 props->info->print(dev, props, buf, sizeof(buf));
806 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
807 }
808 props++;
809 }
810}
811
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100812static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
813{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100814 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200815 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
816 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100817 indent += 2;
818 if (dev->num_gpio_in) {
819 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
820 }
821 if (dev->num_gpio_out) {
822 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
823 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200824 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
825 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200826 if (dev->parent_bus->info->print_dev)
827 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000828 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100829 qbus_print(mon, child, indent);
830 }
831}
832
833static void qbus_print(Monitor *mon, BusState *bus, int indent)
834{
835 struct DeviceState *dev;
836
837 qdev_printf("bus: %s\n", bus->name);
838 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200839 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000840 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100841 qdev_print(mon, dev, indent);
842 }
843}
844#undef qdev_printf
845
846void do_info_qtree(Monitor *mon)
847{
848 if (main_system_bus)
849 qbus_print(mon, main_system_bus, 0);
850}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200851
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200852void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200853{
854 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200855
856 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100857 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200858 }
859}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200860
Markus Armbruster8bc27242010-02-10 20:52:01 +0100861int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200862{
863 QemuOpts *opts;
864
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200865 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100866 if (!opts) {
867 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100868 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100869 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
870 qemu_opts_del(opts);
871 return 0;
872 }
873 if (!qdev_device_add(opts)) {
874 qemu_opts_del(opts);
875 return -1;
876 }
877 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200878}
879
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100880int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200881{
882 const char *id = qdict_get_str(qdict, "id");
883 DeviceState *dev;
884
885 dev = qdev_find_recursive(main_system_bus, id);
886 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100887 qerror_report(QERR_DEVICE_NOT_FOUND, id);
888 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200889 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100890 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200891}
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200892
893static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
894{
895 int l = 0;
896
897 if (dev && dev->parent_bus) {
898 char *d;
899 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
900 if (dev->parent_bus->info->get_fw_dev_path) {
901 d = dev->parent_bus->info->get_fw_dev_path(dev);
902 l += snprintf(p + l, size - l, "%s", d);
903 qemu_free(d);
904 } else {
905 l += snprintf(p + l, size - l, "%s", dev->info->name);
906 }
907 }
908 l += snprintf(p + l , size - l, "/");
909
910 return l;
911}
912
913char* qdev_get_fw_dev_path(DeviceState *dev)
914{
915 char path[128];
916 int l;
917
918 l = qdev_get_fw_dev_path_helper(dev, path, 128);
919
920 path[l-1] = '\0';
921
922 return strdup(path);
923}