blob: 6fc9b02a38e3d2ec5f729748aab44fb409fcd64a [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) {
Stefan Weil68694892010-12-16 19:33:22 +0100110 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100111 }
112
113 info = qdev_find_info(bus->info, name);
114 if (!info) {
115 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
116 }
117
118 return qdev_create_from_info(bus, info);
119}
120
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100121static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200122{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100123 error_printf("name \"%s\", bus %s",
124 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200125 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100126 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200127 }
128 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100129 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200130 }
131 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100132 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200133 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100134 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200135}
136
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200137static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200138{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200139 DeviceState *dev = opaque;
140
141 if (strcmp(name, "driver") == 0)
142 return 0;
143 if (strcmp(name, "bus") == 0)
144 return 0;
145
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100146 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200147 return -1;
148 }
149 return 0;
150}
151
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100152int qdev_device_help(QemuOpts *opts)
153{
154 const char *driver;
155 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100156 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100157
158 driver = qemu_opt_get(opts, "driver");
159 if (driver && !strcmp(driver, "?")) {
160 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100161 if (info->no_user) {
162 continue; /* not available, don't show */
163 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100164 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100165 }
166 return 1;
167 }
168
Markus Armbruster08350cf2010-01-29 19:49:00 +0100169 if (!qemu_opt_get(opts, "?")) {
170 return 0;
171 }
172
173 info = qdev_find_info(NULL, driver);
174 if (!info) {
175 return 0;
176 }
177
178 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100179 /*
180 * TODO Properties without a parser are just for dirty hacks.
181 * qdev_prop_ptr is the only such PropertyInfo. It's marked
182 * for removal. This conditional should be removed along with
183 * it.
184 */
185 if (!prop->info->parse) {
186 continue; /* no way to set it, don't show */
187 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100188 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100189 }
190 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100191}
192
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200193DeviceState *qdev_device_add(QemuOpts *opts)
194{
195 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200196 DeviceInfo *info;
197 DeviceState *qdev;
198 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200199
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200200 driver = qemu_opt_get(opts, "driver");
201 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100202 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200203 return NULL;
204 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200205
206 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200207 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100208 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100209 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100210 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200211 return NULL;
212 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200213
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200214 /* find bus */
215 path = qemu_opt_get(opts, "bus");
216 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200217 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100218 if (!bus) {
219 return NULL;
220 }
221 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100222 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
223 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100224 return NULL;
225 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200226 } else {
227 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100228 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100229 qerror_report(QERR_NO_BUS_FOR_DEVICE,
230 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100231 return NULL;
232 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200233 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200234 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100235 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200236 return NULL;
237 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200238
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200239 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100240 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200241 id = qemu_opts_id(opts);
242 if (id) {
243 qdev->id = id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200244 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200245 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
246 qdev_free(qdev);
247 return NULL;
248 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200249 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100250 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200251 return NULL;
252 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200253 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200254 return qdev;
255}
256
Paul Brookaae94602009-05-14 22:35:06 +0100257/* Initialize a device. Device properties should be set before calling
258 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200259 calling this function.
260 On failure, destroy the device and return negative value.
261 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200262int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100263{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200264 int rc;
265
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200266 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200267 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200268 if (rc < 0) {
269 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200270 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200271 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200272 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600273 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200274 dev->instance_id_alias,
275 dev->alias_required_for_version);
276 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200277 dev->state = DEV_STATE_INITIALIZED;
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200278 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100279}
280
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200281void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
282 int required_for_version)
283{
284 assert(dev->state == DEV_STATE_CREATED);
285 dev->instance_id_alias = alias_id;
286 dev->alias_required_for_version = required_for_version;
287}
288
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200289int qdev_unplug(DeviceState *dev)
290{
291 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100292 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200293 return -1;
294 }
Amit Shah593831d2009-11-02 14:56:41 +0530295 assert(dev->info->unplug != NULL);
296
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200297 return dev->info->unplug(dev);
298}
299
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900300static int qdev_reset_one(DeviceState *dev, void *opaque)
301{
302 if (dev->info->reset) {
303 dev->info->reset(dev);
304 }
305
306 return 0;
307}
308
309BusState *sysbus_get_default(void)
310{
Stefan Weil68694892010-12-16 19:33:22 +0100311 if (!main_system_bus) {
312 main_system_bus = qbus_create(&system_bus_info, NULL,
313 "main-system-bus");
314 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900315 return main_system_bus;
316}
317
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900318static int qbus_reset_one(BusState *bus, void *opaque)
319{
320 if (bus->info->reset) {
321 return bus->info->reset(bus);
322 }
323 return 0;
324}
325
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900326void qdev_reset_all(DeviceState *dev)
327{
328 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
329}
330
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900331void qbus_reset_all(BusState *bus)
332{
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900333 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900334}
335
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200336/* can be used as ->unplug() callback for the simple cases */
337int qdev_simple_unplug_cb(DeviceState *dev)
338{
339 /* just zap it */
340 qdev_free(dev);
341 return 0;
342}
343
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200344/* Like qdev_init(), but terminate program via hw_error() instead of
345 returning an error value. This is okay during machine creation.
346 Don't use for hotplug, because there callers need to recover from
347 failure. Exception: if you know the device's init() callback can't
348 fail, then qdev_init_nofail() can't fail either, and is therefore
349 usable even then. But relying on the device implementation that
350 way is somewhat unclean, and best avoided. */
351void qdev_init_nofail(DeviceState *dev)
352{
353 DeviceInfo *info = dev->info;
354
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200355 if (qdev_init(dev) < 0) {
356 error_report("Initialization of device %s failed\n", info->name);
357 exit(1);
358 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200359}
360
Paul Brook02e2da42009-05-23 00:05:19 +0100361/* Unlink device from bus and free the structure. */
362void qdev_free(DeviceState *dev)
363{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200364 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200365 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200366
367 if (dev->state == DEV_STATE_INITIALIZED) {
368 while (dev->num_child_bus) {
369 bus = QLIST_FIRST(&dev->child_bus);
370 qbus_free(bus);
371 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200372 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600373 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200374 if (dev->info->exit)
375 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200376 if (dev->opts)
377 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200378 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000379 QLIST_REMOVE(dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200380 for (prop = dev->info->props; prop && prop->name; prop++) {
381 if (prop->info->free) {
382 prop->info->free(dev, prop);
383 }
384 }
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200385 qemu_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100386}
387
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200388void qdev_machine_creation_done(void)
389{
390 /*
391 * ok, initial machine setup is done, starting from now we can
392 * only create hotpluggable devices
393 */
394 qdev_hotplug = 1;
395}
396
Paul Brookaae94602009-05-14 22:35:06 +0100397/* Get a character (serial) device interface. */
398CharDriverState *qdev_init_chardev(DeviceState *dev)
399{
400 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530401
402 /* FIXME: This function needs to go away: use chardev properties! */
403 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100404}
405
Paul Brook02e2da42009-05-23 00:05:19 +0100406BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100407{
Paul Brook02e2da42009-05-23 00:05:19 +0100408 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100409}
410
Paul Brookaae94602009-05-14 22:35:06 +0100411void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
412{
413 assert(dev->num_gpio_in == 0);
414 dev->num_gpio_in = n;
415 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
416}
417
418void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
419{
420 assert(dev->num_gpio_out == 0);
421 dev->num_gpio_out = n;
422 dev->gpio_out = pins;
423}
424
425qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
426{
427 assert(n >= 0 && n < dev->num_gpio_in);
428 return dev->gpio_in[n];
429}
430
431void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
432{
433 assert(n >= 0 && n < dev->num_gpio_out);
434 dev->gpio_out[n] = pin;
435}
436
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200437void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
438{
439 qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
440 if (nd->vlan)
441 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
442 if (nd->netdev)
443 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530444 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200445 qdev_prop_exists(dev, "vectors")) {
446 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
447 }
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200448}
449
Paul Brookaae94602009-05-14 22:35:06 +0100450static int next_block_unit[IF_COUNT];
451
452/* Get a block device. This should only be used for single-drive devices
453 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
454 appropriate bus. */
455BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
456{
457 int unit = next_block_unit[type]++;
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200458 DriveInfo *dinfo;
Paul Brookaae94602009-05-14 22:35:06 +0100459
Gerd Hoffmann751c6a12009-07-22 16:42:57 +0200460 dinfo = drive_get(type, 0, unit);
461 return dinfo ? dinfo->bdrv : NULL;
Paul Brookaae94602009-05-14 22:35:06 +0100462}
Paul Brook4d6ae672009-05-14 22:35:06 +0100463
Paul Brook02e2da42009-05-23 00:05:19 +0100464BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100465{
Paul Brook02e2da42009-05-23 00:05:19 +0100466 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100467
Blue Swirl72cf2d42009-09-12 07:36:22 +0000468 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100469 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100470 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100471 }
472 }
473 return NULL;
474}
475
Anthony Liguori81699d82010-11-19 18:55:58 +0900476int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
477 qbus_walkerfn *busfn, void *opaque)
478{
479 DeviceState *dev;
480 int err;
481
482 if (busfn) {
483 err = busfn(bus, opaque);
484 if (err) {
485 return err;
486 }
487 }
488
489 QLIST_FOREACH(dev, &bus->children, sibling) {
490 err = qdev_walk_children(dev, devfn, busfn, opaque);
491 if (err < 0) {
492 return err;
493 }
494 }
495
496 return 0;
497}
498
499int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
500 qbus_walkerfn *busfn, void *opaque)
501{
502 BusState *bus;
503 int err;
504
505 if (devfn) {
506 err = devfn(dev, opaque);
507 if (err) {
508 return err;
509 }
510 }
511
512 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
513 err = qbus_walk_children(bus, devfn, busfn, opaque);
514 if (err < 0) {
515 return err;
516 }
517 }
518
519 return 0;
520}
521
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200522static BusState *qbus_find_recursive(BusState *bus, const char *name,
523 const BusInfo *info)
524{
525 DeviceState *dev;
526 BusState *child, *ret;
527 int match = 1;
528
529 if (name && (strcmp(bus->name, name) != 0)) {
530 match = 0;
531 }
532 if (info && (bus->info != info)) {
533 match = 0;
534 }
535 if (match) {
536 return bus;
537 }
538
Blue Swirl72cf2d42009-09-12 07:36:22 +0000539 QLIST_FOREACH(dev, &bus->children, sibling) {
540 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200541 ret = qbus_find_recursive(child, name, info);
542 if (ret) {
543 return ret;
544 }
545 }
546 }
547 return NULL;
548}
549
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200550static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
551{
552 DeviceState *dev, *ret;
553 BusState *child;
554
555 QLIST_FOREACH(dev, &bus->children, sibling) {
556 if (dev->id && strcmp(dev->id, id) == 0)
557 return dev;
558 QLIST_FOREACH(child, &dev->child_bus, sibling) {
559 ret = qdev_find_recursive(child, id);
560 if (ret) {
561 return ret;
562 }
563 }
564 }
565 return NULL;
566}
567
Markus Armbruster53db16b2010-02-18 18:55:59 +0100568static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200569{
570 BusState *child;
571 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200572
Markus Armbruster53db16b2010-02-18 18:55:59 +0100573 error_printf("child busses at \"%s\":",
574 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000575 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100576 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200577 sep = ", ";
578 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100579 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200580}
581
Markus Armbruster53db16b2010-02-18 18:55:59 +0100582static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200583{
584 DeviceState *dev;
585 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200586
Markus Armbruster53db16b2010-02-18 18:55:59 +0100587 error_printf("devices at \"%s\":", bus->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000588 QLIST_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100589 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200590 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100591 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200592 sep = ", ";
593 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100594 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200595}
596
597static BusState *qbus_find_bus(DeviceState *dev, char *elem)
598{
599 BusState *child;
600
Blue Swirl72cf2d42009-09-12 07:36:22 +0000601 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200602 if (strcmp(child->name, elem) == 0) {
603 return child;
604 }
605 }
606 return NULL;
607}
608
609static DeviceState *qbus_find_dev(BusState *bus, char *elem)
610{
611 DeviceState *dev;
612
613 /*
614 * try to match in order:
615 * (1) instance id, if present
616 * (2) driver name
617 * (3) driver alias, if present
618 */
Blue Swirl72cf2d42009-09-12 07:36:22 +0000619 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200620 if (dev->id && strcmp(dev->id, elem) == 0) {
621 return dev;
622 }
623 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000624 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200625 if (strcmp(dev->info->name, elem) == 0) {
626 return dev;
627 }
628 }
Blue Swirl72cf2d42009-09-12 07:36:22 +0000629 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200630 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
631 return dev;
632 }
633 }
634 return NULL;
635}
636
637static BusState *qbus_find(const char *path)
638{
639 DeviceState *dev;
640 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100641 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200642 int pos, len;
643
644 /* find start element */
645 if (path[0] == '/') {
646 bus = main_system_bus;
647 pos = 0;
648 } else {
649 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100650 assert(!path[0]);
651 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200652 }
653 bus = qbus_find_recursive(main_system_bus, elem, NULL);
654 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100655 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200656 return NULL;
657 }
658 pos = len;
659 }
660
661 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100662 assert(path[pos] == '/' || !path[pos]);
663 while (path[pos] == '/') {
664 pos++;
665 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200666 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200667 return bus;
668 }
669
670 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100671 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
672 assert(0);
673 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200674 }
675 pos += len;
676 dev = qbus_find_dev(bus, elem);
677 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100678 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100679 if (!monitor_cur_is_qmp()) {
680 qbus_list_dev(bus);
681 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200682 return NULL;
683 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100684
685 assert(path[pos] == '/' || !path[pos]);
686 while (path[pos] == '/') {
687 pos++;
688 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200689 if (path[pos] == '\0') {
690 /* last specified element is a device. If it has exactly
691 * one child bus accept it nevertheless */
692 switch (dev->num_child_bus) {
693 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100694 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200695 return NULL;
696 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000697 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200698 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100699 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100700 if (!monitor_cur_is_qmp()) {
701 qbus_list_bus(dev);
702 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200703 return NULL;
704 }
705 }
706
707 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100708 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
709 assert(0);
710 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200711 }
712 pos += len;
713 bus = qbus_find_bus(dev, elem);
714 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100715 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100716 if (!monitor_cur_is_qmp()) {
717 qbus_list_bus(dev);
718 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200719 return NULL;
720 }
721 }
722}
723
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200724void qbus_create_inplace(BusState *bus, BusInfo *info,
725 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100726{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200727 char *buf;
728 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100729
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200730 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100731 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200732
733 if (name) {
734 /* use supplied name */
735 bus->name = qemu_strdup(name);
736 } else if (parent && parent->id) {
737 /* parent device has id -> use it for bus name */
738 len = strlen(parent->id) + 16;
739 buf = qemu_malloc(len);
740 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
741 bus->name = buf;
742 } else {
743 /* no id -> use lowercase bus type for bus name */
744 len = strlen(info->name) + 16;
745 buf = qemu_malloc(len);
746 len = snprintf(buf, len, "%s.%d", info->name,
747 parent ? parent->num_child_bus : 0);
748 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200749 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200750 bus->name = buf;
751 }
752
Blue Swirl72cf2d42009-09-12 07:36:22 +0000753 QLIST_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100754 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000755 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200756 parent->num_child_bus++;
Paul Brook02e2da42009-05-23 00:05:19 +0100757 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200758
759}
760
761BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
762{
763 BusState *bus;
764
765 bus = qemu_mallocz(info->size);
766 bus->qdev_allocated = 1;
767 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100768 return bus;
769}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100770
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200771void qbus_free(BusState *bus)
772{
773 DeviceState *dev;
774
775 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
776 qdev_free(dev);
777 }
778 if (bus->parent) {
779 QLIST_REMOVE(bus, sibling);
780 bus->parent->num_child_bus--;
781 }
Isaku Yamahatae163ae72010-05-27 14:35:58 +0900782 qemu_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200783 if (bus->qdev_allocated) {
784 qemu_free(bus);
785 }
786}
787
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100788#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
789static void qbus_print(Monitor *mon, BusState *bus, int indent);
790
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200791static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
792 const char *prefix, int indent)
793{
794 char buf[64];
795
796 if (!props)
797 return;
798 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100799 /*
800 * TODO Properties without a print method are just for dirty
801 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
802 * marked for removal. The test props->info->print should be
803 * removed along with it.
804 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200805 if (props->info->print) {
806 props->info->print(dev, props, buf, sizeof(buf));
807 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
808 }
809 props++;
810 }
811}
812
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100813static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
814{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100815 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200816 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
817 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100818 indent += 2;
819 if (dev->num_gpio_in) {
820 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
821 }
822 if (dev->num_gpio_out) {
823 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
824 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200825 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
826 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200827 if (dev->parent_bus->info->print_dev)
828 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000829 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100830 qbus_print(mon, child, indent);
831 }
832}
833
834static void qbus_print(Monitor *mon, BusState *bus, int indent)
835{
836 struct DeviceState *dev;
837
838 qdev_printf("bus: %s\n", bus->name);
839 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200840 qdev_printf("type %s\n", bus->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000841 QLIST_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100842 qdev_print(mon, dev, indent);
843 }
844}
845#undef qdev_printf
846
847void do_info_qtree(Monitor *mon)
848{
849 if (main_system_bus)
850 qbus_print(mon, main_system_bus, 0);
851}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200852
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200853void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200854{
855 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200856
857 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100858 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200859 }
860}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200861
Markus Armbruster8bc27242010-02-10 20:52:01 +0100862int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200863{
864 QemuOpts *opts;
865
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200866 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100867 if (!opts) {
868 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100869 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100870 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
871 qemu_opts_del(opts);
872 return 0;
873 }
874 if (!qdev_device_add(opts)) {
875 qemu_opts_del(opts);
876 return -1;
877 }
878 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200879}
880
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100881int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200882{
883 const char *id = qdict_get_str(qdict, "id");
884 DeviceState *dev;
885
886 dev = qdev_find_recursive(main_system_bus, id);
887 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100888 qerror_report(QERR_DEVICE_NOT_FOUND, id);
889 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200890 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100891 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200892}
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200893
894static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
895{
896 int l = 0;
897
898 if (dev && dev->parent_bus) {
899 char *d;
900 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
901 if (dev->parent_bus->info->get_fw_dev_path) {
902 d = dev->parent_bus->info->get_fw_dev_path(dev);
903 l += snprintf(p + l, size - l, "%s", d);
904 qemu_free(d);
905 } else {
906 l += snprintf(p + l, size - l, "%s", dev->info->name);
907 }
908 }
909 l += snprintf(p + l , size - l, "/");
910
911 return l;
912}
913
914char* qdev_get_fw_dev_path(DeviceState *dev)
915{
916 char path[128];
917 int l;
918
919 l = qdev_get_fw_dev_path_helper(dev, path, 128);
920
921 path[l-1] = '\0';
922
923 return strdup(path);
924}