blob: 0465632dff5afddc79b32fea77f71bc3e99ca3bb [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"
Paul Brookaae94602009-05-14 22:35:06 +010032
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020033static int qdev_hotplug = 0;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070034static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020036
Gerd Hoffmanncdaed7c2009-10-06 21:17:52 +020037/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
Blue Swirlb9aaf7f2009-06-09 18:38:51 +000038static BusState *main_system_bus;
Isaku Yamahata2da8bb92011-08-02 10:59:13 +090039static void main_system_bus_create(void);
Paul Brook4d6ae672009-05-14 22:35:06 +010040
Gerd Hoffmann0958b4c2009-10-26 15:56:45 +010041DeviceInfo *device_info_list;
Paul Brookaae94602009-05-14 22:35:06 +010042
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +020043static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 const BusInfo *info);
45static BusState *qbus_find(const char *path);
46
Paul Brookaae94602009-05-14 22:35:06 +010047/* Register a new device type. */
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020048void qdev_register(DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010049{
Gerd Hoffmann074f2ff2009-06-10 09:41:42 +020050 assert(info->size >= sizeof(DeviceState));
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020051 assert(!info->next);
Paul Brookaae94602009-05-14 22:35:06 +010052
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020053 info->next = device_info_list;
54 device_info_list = info;
Paul Brookaae94602009-05-14 22:35:06 +010055}
56
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020057static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
58{
59 DeviceInfo *info;
60
Gerd Hoffmann3320e562009-07-15 13:43:33 +020061 /* first check device names */
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020062 for (info = device_info_list; info != NULL; info = info->next) {
63 if (bus_info && info->bus_info != bus_info)
64 continue;
65 if (strcmp(info->name, name) != 0)
66 continue;
67 return info;
68 }
Gerd Hoffmann3320e562009-07-15 13:43:33 +020069
70 /* failing that check the aliases */
71 for (info = device_info_list; info != NULL; info = info->next) {
72 if (bus_info && info->bus_info != bus_info)
73 continue;
74 if (!info->alias)
75 continue;
76 if (strcmp(info->alias, name) != 0)
77 continue;
78 return info;
79 }
Gerd Hoffmann81ebb982009-07-15 13:43:32 +020080 return NULL;
81}
82
Paolo Bonzinica2cc782011-12-18 17:05:11 +010083static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
84 Error **errp);
85
Markus Armbruster0c175422010-02-19 19:12:18 +010086static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
Paul Brookaae94602009-05-14 22:35:06 +010087{
Paul Brookaae94602009-05-14 22:35:06 +010088 DeviceState *dev;
Anthony Liguoria5296ca2011-12-12 14:29:27 -060089 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010090
Markus Armbruster0c175422010-02-19 19:12:18 +010091 assert(bus->info == info->bus_info);
Anthony Liguori7267c092011-08-20 22:09:37 -050092 dev = g_malloc0(info->size);
Gerd Hoffmann042f84d2009-06-30 14:12:09 +020093 dev->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +010094 dev->parent_bus = bus;
Gerd Hoffmannee6847d2009-07-15 13:43:31 +020095 qdev_prop_set_defaults(dev, dev->info->props);
96 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Gerd Hoffmann458fb672009-12-08 13:11:33 +010097 qdev_prop_set_globals(dev);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +020098 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020099 if (qdev_hotplug) {
100 assert(bus->allow_hotplug);
101 dev->hotplugged = 1;
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700102 qdev_hot_added = true;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200103 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200104 dev->instance_id_alias = -1;
Anthony Liguori44677de2011-12-12 14:29:26 -0600105 QTAILQ_INIT(&dev->properties);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200106 dev->state = DEV_STATE_CREATED;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600107
108 for (prop = dev->info->props; prop && prop->name; prop++) {
109 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100110 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600111 }
112
113 for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
114 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100115 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600116 }
117
Anthony Liguoricd34d662011-12-12 14:29:43 -0600118 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
119
Paul Brookaae94602009-05-14 22:35:06 +0100120 return dev;
121}
122
Markus Armbruster0c175422010-02-19 19:12:18 +0100123/* Create a new device. This only initializes the device state structure
124 and allows properties to be set. qdev_init should be called to
125 initialize the actual device emulation. */
126DeviceState *qdev_create(BusState *bus, const char *name)
127{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000128 DeviceState *dev;
129
130 dev = qdev_try_create(bus, name);
131 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100132 if (bus) {
133 hw_error("Unknown device '%s' for bus '%s'\n", name,
134 bus->info->name);
135 } else {
136 hw_error("Unknown device '%s' for default sysbus\n", name);
137 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000138 }
139
140 return dev;
141}
142
143DeviceState *qdev_try_create(BusState *bus, const char *name)
144{
Markus Armbruster0c175422010-02-19 19:12:18 +0100145 DeviceInfo *info;
146
147 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100148 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100149 }
150
151 info = qdev_find_info(bus->info, name);
152 if (!info) {
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000153 return NULL;
Markus Armbruster0c175422010-02-19 19:12:18 +0100154 }
155
156 return qdev_create_from_info(bus, info);
157}
158
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100159static void qdev_print_devinfo(DeviceInfo *info)
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200160{
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100161 error_printf("name \"%s\", bus %s",
162 info->name, info->bus_info->name);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200163 if (info->alias) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100164 error_printf(", alias \"%s\"", info->alias);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200165 }
166 if (info->desc) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100167 error_printf(", desc \"%s\"", info->desc);
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200168 }
169 if (info->no_user) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100170 error_printf(", no-user");
Gerd Hoffmann22f2e342009-08-03 11:26:48 +0200171 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100172 error_printf("\n");
Gerd Hoffmann1b524b02009-07-29 13:12:23 +0200173}
174
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200175static int set_property(const char *name, const char *value, void *opaque)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200176{
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200177 DeviceState *dev = opaque;
178
179 if (strcmp(name, "driver") == 0)
180 return 0;
181 if (strcmp(name, "bus") == 0)
182 return 0;
183
Mark McLoughlin3df04ac2009-09-23 11:24:05 +0100184 if (qdev_prop_parse(dev, name, value) == -1) {
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200185 return -1;
186 }
187 return 0;
188}
189
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100190int qdev_device_help(QemuOpts *opts)
191{
192 const char *driver;
193 DeviceInfo *info;
Markus Armbruster08350cf2010-01-29 19:49:00 +0100194 Property *prop;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100195
196 driver = qemu_opt_get(opts, "driver");
197 if (driver && !strcmp(driver, "?")) {
198 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100199 if (info->no_user) {
200 continue; /* not available, don't show */
201 }
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100202 qdev_print_devinfo(info);
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100203 }
204 return 1;
205 }
206
Markus Armbruster542379f2011-11-08 11:00:38 +0100207 if (!driver || !qemu_opt_get(opts, "?")) {
Markus Armbruster08350cf2010-01-29 19:49:00 +0100208 return 0;
209 }
210
211 info = qdev_find_info(NULL, driver);
212 if (!info) {
213 return 0;
214 }
215
216 for (prop = info->props; prop && prop->name; prop++) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100217 /*
218 * TODO Properties without a parser are just for dirty hacks.
219 * qdev_prop_ptr is the only such PropertyInfo. It's marked
220 * for removal. This conditional should be removed along with
221 * it.
222 */
223 if (!prop->info->parse) {
224 continue; /* no way to set it, don't show */
225 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100226 error_printf("%s.%s=%s\n", info->name, prop->name,
227 prop->info->legacy_name ?: prop->info->name);
Markus Armbruster08350cf2010-01-29 19:49:00 +0100228 }
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200229 for (prop = info->bus_info->props; prop && prop->name; prop++) {
230 if (!prop->info->parse) {
231 continue; /* no way to set it, don't show */
232 }
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100233 error_printf("%s.%s=%s\n", info->name, prop->name,
234 prop->info->legacy_name ?: prop->info->name);
Gerd Hoffmanna8467c72011-09-16 11:25:05 +0200235 }
Markus Armbruster08350cf2010-01-29 19:49:00 +0100236 return 1;
Markus Armbrusterff952ba2010-01-29 19:48:57 +0100237}
238
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600239static DeviceState *qdev_get_peripheral(void)
240{
241 static DeviceState *dev;
242
243 if (dev == NULL) {
244 dev = qdev_create(NULL, "container");
245 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
246 qdev_init_nofail(dev);
247 }
248
249 return dev;
250}
251
Anthony Liguori8eb02832011-12-12 14:29:37 -0600252static DeviceState *qdev_get_peripheral_anon(void)
253{
254 static DeviceState *dev;
255
256 if (dev == NULL) {
257 dev = qdev_create(NULL, "container");
258 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
259 qdev_init_nofail(dev);
260 }
261
262 return dev;
263}
264
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200265DeviceState *qdev_device_add(QemuOpts *opts)
266{
267 const char *driver, *path, *id;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200268 DeviceInfo *info;
269 DeviceState *qdev;
270 BusState *bus;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200271
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200272 driver = qemu_opt_get(opts, "driver");
273 if (!driver) {
Markus Armbruster02042762010-02-19 14:17:34 +0100274 qerror_report(QERR_MISSING_PARAMETER, "driver");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200275 return NULL;
276 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200277
278 /* find driver */
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200279 info = qdev_find_info(NULL, driver);
Markus Armbrusterc64eafa2010-02-19 13:31:49 +0100280 if (!info || info->no_user) {
Markus Armbrustere17ba872010-03-25 17:22:36 +0100281 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
Markus Armbruster02042762010-02-19 14:17:34 +0100282 error_printf_unless_qmp("Try with argument '?' for a list.\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200283 return NULL;
284 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200285
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200286 /* find bus */
287 path = qemu_opt_get(opts, "bus");
288 if (path != NULL) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200289 bus = qbus_find(path);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100290 if (!bus) {
291 return NULL;
292 }
293 if (bus->info != info->bus_info) {
Markus Armbruster02042762010-02-19 14:17:34 +0100294 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
295 driver, bus->info->name);
Markus Armbruster327867b2010-02-19 19:08:45 +0100296 return NULL;
297 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200298 } else {
299 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100300 if (!bus) {
Markus Armbruster02042762010-02-19 14:17:34 +0100301 qerror_report(QERR_NO_BUS_FOR_DEVICE,
302 info->name, info->bus_info->name);
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100303 return NULL;
304 }
Gerd Hoffmann75570082009-08-31 14:23:58 +0200305 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200306 if (qdev_hotplug && !bus->allow_hotplug) {
Markus Armbruster02042762010-02-19 14:17:34 +0100307 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200308 return NULL;
309 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200310
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200311 /* create device, set properties */
Markus Armbruster0c175422010-02-19 19:12:18 +0100312 qdev = qdev_create_from_info(bus, info);
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200313 id = qemu_opts_id(opts);
314 if (id) {
315 qdev->id = id;
Anthony Liguori1bdaacb2011-12-12 14:29:36 -0600316 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
Anthony Liguori8eb02832011-12-12 14:29:37 -0600317 } else {
318 static int anon_count;
319 gchar *name = g_strdup_printf("device[%d]", anon_count++);
320 qdev_property_add_child(qdev_get_peripheral_anon(), name,
321 qdev, NULL);
322 g_free(name);
323 }
Gerd Hoffmannf31d07d2009-07-31 12:25:37 +0200324 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
325 qdev_free(qdev);
326 return NULL;
327 }
Markus Armbruster5c17ca22009-10-07 01:16:01 +0200328 if (qdev_init(qdev) < 0) {
Markus Armbruster02042762010-02-19 14:17:34 +0100329 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200330 return NULL;
331 }
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200332 qdev->opts = opts;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200333 return qdev;
334}
335
Paul Brookaae94602009-05-14 22:35:06 +0100336/* Initialize a device. Device properties should be set before calling
337 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200338 calling this function.
339 On failure, destroy the device and return negative value.
340 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200341int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100342{
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200343 int rc;
344
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200345 assert(dev->state == DEV_STATE_CREATED);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200346 rc = dev->info->init(dev, dev->info);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200347 if (rc < 0) {
348 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200349 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200350 }
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200351 if (dev->info->vmsd) {
Alex Williamson0be71e32010-06-25 11:09:07 -0600352 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200353 dev->instance_id_alias,
354 dev->alias_required_for_version);
355 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200356 dev->state = DEV_STATE_INITIALIZED;
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200357 if (dev->hotplugged && dev->info->reset) {
358 dev->info->reset(dev);
359 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200360 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100361}
362
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200363void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
364 int required_for_version)
365{
366 assert(dev->state == DEV_STATE_CREATED);
367 dev->instance_id_alias = alias_id;
368 dev->alias_required_for_version = required_for_version;
369}
370
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200371int qdev_unplug(DeviceState *dev)
372{
373 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100374 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200375 return -1;
376 }
Amit Shah593831d2009-11-02 14:56:41 +0530377 assert(dev->info->unplug != NULL);
378
Anthony Liguori85ed3032011-12-12 14:29:25 -0600379 if (dev->ref != 0) {
380 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
381 return -1;
382 }
383
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700384 qdev_hot_removed = true;
385
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200386 return dev->info->unplug(dev);
387}
388
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900389static int qdev_reset_one(DeviceState *dev, void *opaque)
390{
391 if (dev->info->reset) {
392 dev->info->reset(dev);
393 }
394
395 return 0;
396}
397
398BusState *sysbus_get_default(void)
399{
Stefan Weil68694892010-12-16 19:33:22 +0100400 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900401 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100402 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900403 return main_system_bus;
404}
405
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900406static int qbus_reset_one(BusState *bus, void *opaque)
407{
408 if (bus->info->reset) {
409 return bus->info->reset(bus);
410 }
411 return 0;
412}
413
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900414void qdev_reset_all(DeviceState *dev)
415{
416 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
417}
418
Isaku Yamahata80376c32010-12-20 14:33:35 +0900419void qbus_reset_all_fn(void *opaque)
420{
421 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200422 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900423}
424
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200425/* can be used as ->unplug() callback for the simple cases */
426int qdev_simple_unplug_cb(DeviceState *dev)
427{
428 /* just zap it */
429 qdev_free(dev);
430 return 0;
431}
432
Michael Tokarev3b29a102011-04-06 17:51:59 +0400433
434/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200435 returning an error value. This is okay during machine creation.
436 Don't use for hotplug, because there callers need to recover from
437 failure. Exception: if you know the device's init() callback can't
438 fail, then qdev_init_nofail() can't fail either, and is therefore
439 usable even then. But relying on the device implementation that
440 way is somewhat unclean, and best avoided. */
441void qdev_init_nofail(DeviceState *dev)
442{
443 DeviceInfo *info = dev->info;
444
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200445 if (qdev_init(dev) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200446 error_report("Initialization of device %s failed", info->name);
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200447 exit(1);
448 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200449}
450
Anthony Liguori44677de2011-12-12 14:29:26 -0600451static void qdev_property_del_all(DeviceState *dev)
452{
453 while (!QTAILQ_EMPTY(&dev->properties)) {
454 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
455
456 QTAILQ_REMOVE(&dev->properties, prop, node);
457
458 if (prop->release) {
459 prop->release(dev, prop->name, prop->opaque);
460 }
461
462 g_free(prop->name);
463 g_free(prop->type);
464 g_free(prop);
465 }
466}
467
Paul Brook02e2da42009-05-23 00:05:19 +0100468/* Unlink device from bus and free the structure. */
469void qdev_free(DeviceState *dev)
470{
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200471 BusState *bus;
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200472 Property *prop;
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200473
Anthony Liguori44677de2011-12-12 14:29:26 -0600474 qdev_property_del_all(dev);
475
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200476 if (dev->state == DEV_STATE_INITIALIZED) {
477 while (dev->num_child_bus) {
478 bus = QLIST_FIRST(&dev->child_bus);
479 qbus_free(bus);
480 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200481 if (dev->info->vmsd)
Alex Williamson0be71e32010-06-25 11:09:07 -0600482 vmstate_unregister(dev, dev->info->vmsd, dev);
Gerd Hoffmannd29275f2009-09-25 21:42:35 +0200483 if (dev->info->exit)
484 dev->info->exit(dev);
Gerd Hoffmannef80b462009-09-25 21:42:49 +0200485 if (dev->opts)
486 qemu_opts_del(dev->opts);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200487 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200488 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Markus Armbrusterd21357d2010-06-01 20:32:31 +0200489 for (prop = dev->info->props; prop && prop->name; prop++) {
490 if (prop->info->free) {
491 prop->info->free(dev, prop);
492 }
493 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500494 g_free(dev);
Paul Brookaae94602009-05-14 22:35:06 +0100495}
496
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200497void qdev_machine_creation_done(void)
498{
499 /*
500 * ok, initial machine setup is done, starting from now we can
501 * only create hotpluggable devices
502 */
503 qdev_hotplug = 1;
504}
505
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700506bool qdev_machine_modified(void)
507{
508 return qdev_hot_added || qdev_hot_removed;
509}
510
Paul Brookaae94602009-05-14 22:35:06 +0100511/* Get a character (serial) device interface. */
512CharDriverState *qdev_init_chardev(DeviceState *dev)
513{
514 static int next_serial;
Amit Shah98b19252010-01-20 00:36:52 +0530515
516 /* FIXME: This function needs to go away: use chardev properties! */
517 return serial_hds[next_serial++];
Paul Brookaae94602009-05-14 22:35:06 +0100518}
519
Paul Brook02e2da42009-05-23 00:05:19 +0100520BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100521{
Paul Brook02e2da42009-05-23 00:05:19 +0100522 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100523}
524
Paul Brookaae94602009-05-14 22:35:06 +0100525void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
526{
527 assert(dev->num_gpio_in == 0);
528 dev->num_gpio_in = n;
529 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
530}
531
532void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
533{
534 assert(dev->num_gpio_out == 0);
535 dev->num_gpio_out = n;
536 dev->gpio_out = pins;
537}
538
539qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
540{
541 assert(n >= 0 && n < dev->num_gpio_in);
542 return dev->gpio_in[n];
543}
544
545void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
546{
547 assert(n >= 0 && n < dev->num_gpio_out);
548 dev->gpio_out[n] = pin;
549}
550
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200551void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
552{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200553 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200554 if (nd->vlan)
555 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
556 if (nd->netdev)
557 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530558 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200559 qdev_prop_exists(dev, "vectors")) {
560 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
561 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100562 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200563}
564
Paul Brook02e2da42009-05-23 00:05:19 +0100565BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100566{
Paul Brook02e2da42009-05-23 00:05:19 +0100567 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100568
Blue Swirl72cf2d42009-09-12 07:36:22 +0000569 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100570 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100571 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100572 }
573 }
574 return NULL;
575}
576
Anthony Liguori81699d82010-11-19 18:55:58 +0900577int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
578 qbus_walkerfn *busfn, void *opaque)
579{
580 DeviceState *dev;
581 int err;
582
583 if (busfn) {
584 err = busfn(bus, opaque);
585 if (err) {
586 return err;
587 }
588 }
589
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200590 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900591 err = qdev_walk_children(dev, devfn, busfn, opaque);
592 if (err < 0) {
593 return err;
594 }
595 }
596
597 return 0;
598}
599
600int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
601 qbus_walkerfn *busfn, void *opaque)
602{
603 BusState *bus;
604 int err;
605
606 if (devfn) {
607 err = devfn(dev, opaque);
608 if (err) {
609 return err;
610 }
611 }
612
613 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
614 err = qbus_walk_children(bus, devfn, busfn, opaque);
615 if (err < 0) {
616 return err;
617 }
618 }
619
620 return 0;
621}
622
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200623static BusState *qbus_find_recursive(BusState *bus, const char *name,
624 const BusInfo *info)
625{
626 DeviceState *dev;
627 BusState *child, *ret;
628 int match = 1;
629
630 if (name && (strcmp(bus->name, name) != 0)) {
631 match = 0;
632 }
633 if (info && (bus->info != info)) {
634 match = 0;
635 }
636 if (match) {
637 return bus;
638 }
639
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200640 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000641 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200642 ret = qbus_find_recursive(child, name, info);
643 if (ret) {
644 return ret;
645 }
646 }
647 }
648 return NULL;
649}
650
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900651DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200652{
653 DeviceState *dev, *ret;
654 BusState *child;
655
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200656 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200657 if (dev->id && strcmp(dev->id, id) == 0)
658 return dev;
659 QLIST_FOREACH(child, &dev->child_bus, sibling) {
660 ret = qdev_find_recursive(child, id);
661 if (ret) {
662 return ret;
663 }
664 }
665 }
666 return NULL;
667}
668
Markus Armbruster53db16b2010-02-18 18:55:59 +0100669static void qbus_list_bus(DeviceState *dev)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200670{
671 BusState *child;
672 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200673
Markus Armbruster53db16b2010-02-18 18:55:59 +0100674 error_printf("child busses at \"%s\":",
675 dev->id ? dev->id : dev->info->name);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000676 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100677 error_printf("%s\"%s\"", sep, child->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200678 sep = ", ";
679 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100680 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200681}
682
Markus Armbruster53db16b2010-02-18 18:55:59 +0100683static void qbus_list_dev(BusState *bus)
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200684{
685 DeviceState *dev;
686 const char *sep = " ";
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200687
Markus Armbruster53db16b2010-02-18 18:55:59 +0100688 error_printf("devices at \"%s\":", bus->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200689 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Markus Armbruster53db16b2010-02-18 18:55:59 +0100690 error_printf("%s\"%s\"", sep, dev->info->name);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200691 if (dev->id)
Markus Armbruster53db16b2010-02-18 18:55:59 +0100692 error_printf("/\"%s\"", dev->id);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200693 sep = ", ";
694 }
Markus Armbruster53db16b2010-02-18 18:55:59 +0100695 error_printf("\n");
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200696}
697
698static BusState *qbus_find_bus(DeviceState *dev, char *elem)
699{
700 BusState *child;
701
Blue Swirl72cf2d42009-09-12 07:36:22 +0000702 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200703 if (strcmp(child->name, elem) == 0) {
704 return child;
705 }
706 }
707 return NULL;
708}
709
710static DeviceState *qbus_find_dev(BusState *bus, char *elem)
711{
712 DeviceState *dev;
713
714 /*
715 * try to match in order:
716 * (1) instance id, if present
717 * (2) driver name
718 * (3) driver alias, if present
719 */
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200720 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200721 if (dev->id && strcmp(dev->id, elem) == 0) {
722 return dev;
723 }
724 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200725 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200726 if (strcmp(dev->info->name, elem) == 0) {
727 return dev;
728 }
729 }
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200730 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200731 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
732 return dev;
733 }
734 }
735 return NULL;
736}
737
738static BusState *qbus_find(const char *path)
739{
740 DeviceState *dev;
741 BusState *bus;
Markus Armbruster53db16b2010-02-18 18:55:59 +0100742 char elem[128];
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200743 int pos, len;
744
745 /* find start element */
746 if (path[0] == '/') {
747 bus = main_system_bus;
748 pos = 0;
749 } else {
750 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100751 assert(!path[0]);
752 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200753 }
754 bus = qbus_find_recursive(main_system_bus, elem, NULL);
755 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100756 qerror_report(QERR_BUS_NOT_FOUND, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200757 return NULL;
758 }
759 pos = len;
760 }
761
762 for (;;) {
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100763 assert(path[pos] == '/' || !path[pos]);
764 while (path[pos] == '/') {
765 pos++;
766 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200767 if (path[pos] == '\0') {
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200768 return bus;
769 }
770
771 /* find device */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100772 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
773 assert(0);
774 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200775 }
776 pos += len;
777 dev = qbus_find_dev(bus, elem);
778 if (!dev) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100779 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100780 if (!monitor_cur_is_qmp()) {
781 qbus_list_dev(bus);
782 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200783 return NULL;
784 }
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100785
786 assert(path[pos] == '/' || !path[pos]);
787 while (path[pos] == '/') {
788 pos++;
789 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200790 if (path[pos] == '\0') {
791 /* last specified element is a device. If it has exactly
792 * one child bus accept it nevertheless */
793 switch (dev->num_child_bus) {
794 case 0:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100795 qerror_report(QERR_DEVICE_NO_BUS, elem);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200796 return NULL;
797 case 1:
Blue Swirl72cf2d42009-09-12 07:36:22 +0000798 return QLIST_FIRST(&dev->child_bus);
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200799 default:
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100800 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100801 if (!monitor_cur_is_qmp()) {
802 qbus_list_bus(dev);
803 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200804 return NULL;
805 }
806 }
807
808 /* find bus */
Markus Armbrusterfc98eb42010-02-19 16:09:25 +0100809 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
810 assert(0);
811 elem[0] = len = 0;
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200812 }
813 pos += len;
814 bus = qbus_find_bus(dev, elem);
815 if (!bus) {
Markus Armbrusterac8dae62010-02-19 18:09:33 +0100816 qerror_report(QERR_BUS_NOT_FOUND, elem);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100817 if (!monitor_cur_is_qmp()) {
818 qbus_list_bus(dev);
819 }
Gerd Hoffmann8ffb1bc2009-07-15 13:59:25 +0200820 return NULL;
821 }
822 }
823}
824
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200825void qbus_create_inplace(BusState *bus, BusInfo *info,
826 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100827{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200828 char *buf;
829 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100830
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200831 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100832 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200833
834 if (name) {
835 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500836 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200837 } else if (parent && parent->id) {
838 /* parent device has id -> use it for bus name */
839 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500840 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200841 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
842 bus->name = buf;
843 } else {
844 /* no id -> use lowercase bus type for bus name */
845 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500846 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200847 len = snprintf(buf, len, "%s.%d", info->name,
848 parent ? parent->num_child_bus : 0);
849 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200850 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200851 bus->name = buf;
852 }
853
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200854 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100855 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000856 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200857 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900858 } else if (bus != main_system_bus) {
859 /* TODO: once all bus devices are qdevified,
860 only reset handler for main_system_bus should be registered here. */
861 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100862 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200863}
864
865BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
866{
867 BusState *bus;
868
Anthony Liguori7267c092011-08-20 22:09:37 -0500869 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200870 bus->qdev_allocated = 1;
871 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100872 return bus;
873}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100874
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900875static void main_system_bus_create(void)
876{
877 /* assign main_system_bus before qbus_create_inplace()
878 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500879 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900880 main_system_bus->qdev_allocated = 1;
881 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
882 "main-system-bus");
883}
884
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200885void qbus_free(BusState *bus)
886{
887 DeviceState *dev;
888
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200889 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200890 qdev_free(dev);
891 }
892 if (bus->parent) {
893 QLIST_REMOVE(bus, sibling);
894 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900895 } else {
896 assert(bus != main_system_bus); /* main_system_bus is never freed */
897 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200898 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500899 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200900 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500901 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200902 }
903}
904
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100905#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
906static void qbus_print(Monitor *mon, BusState *bus, int indent);
907
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200908static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
909 const char *prefix, int indent)
910{
911 char buf[64];
912
913 if (!props)
914 return;
915 while (props->name) {
Markus Armbruster036f7162010-02-19 11:47:06 +0100916 /*
917 * TODO Properties without a print method are just for dirty
918 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
919 * marked for removal. The test props->info->print should be
920 * removed along with it.
921 */
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200922 if (props->info->print) {
923 props->info->print(dev, props, buf, sizeof(buf));
924 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
925 }
926 props++;
927 }
928}
929
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100930static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
931{
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100932 BusState *child;
Gerd Hoffmannccb63de2009-07-15 13:43:34 +0200933 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
934 dev->id ? dev->id : "");
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100935 indent += 2;
936 if (dev->num_gpio_in) {
937 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
938 }
939 if (dev->num_gpio_out) {
940 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
941 }
Gerd Hoffmannee6847d2009-07-15 13:43:31 +0200942 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
943 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200944 if (dev->parent_bus->info->print_dev)
945 dev->parent_bus->info->print_dev(mon, dev, indent);
Blue Swirl72cf2d42009-09-12 07:36:22 +0000946 QLIST_FOREACH(child, &dev->child_bus, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100947 qbus_print(mon, child, indent);
948 }
949}
950
951static void qbus_print(Monitor *mon, BusState *bus, int indent)
952{
953 struct DeviceState *dev;
954
955 qdev_printf("bus: %s\n", bus->name);
956 indent += 2;
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200957 qdev_printf("type %s\n", bus->info->name);
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200958 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100959 qdev_print(mon, dev, indent);
960 }
961}
962#undef qdev_printf
963
964void do_info_qtree(Monitor *mon)
965{
966 if (main_system_bus)
967 qbus_print(mon, main_system_bus, 0);
968}
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200969
Gerd Hoffmannf6c64e02009-08-03 15:03:09 +0200970void do_info_qdm(Monitor *mon)
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200971{
972 DeviceInfo *info;
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200973
974 for (info = device_info_list; info != NULL; info = info->next) {
Markus Armbruster8a9662c2010-02-18 18:44:15 +0100975 qdev_print_devinfo(info);
Gerd Hoffmann9316d302009-07-29 13:12:24 +0200976 }
977}
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200978
Markus Armbruster8bc27242010-02-10 20:52:01 +0100979int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200980{
981 QemuOpts *opts;
982
Gerd Hoffmann3329f072010-08-20 13:52:01 +0200983 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
Markus Armbruster8bc27242010-02-10 20:52:01 +0100984 if (!opts) {
985 return -1;
Kevin Wolf0f853a32010-02-16 13:12:38 +0100986 }
Markus Armbruster8bc27242010-02-10 20:52:01 +0100987 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
988 qemu_opts_del(opts);
989 return 0;
990 }
991 if (!qdev_device_add(opts)) {
992 qemu_opts_del(opts);
993 return -1;
994 }
995 return 0;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200996}
997
Markus Armbruster17a38ea2010-03-22 11:38:14 +0100998int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200999{
1000 const char *id = qdict_get_str(qdict, "id");
1001 DeviceState *dev;
1002
1003 dev = qdev_find_recursive(main_system_bus, id);
1004 if (NULL == dev) {
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001005 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1006 return -1;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001007 }
Markus Armbruster17a38ea2010-03-22 11:38:14 +01001008 return qdev_unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +02001009}
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001010
1011static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1012{
1013 int l = 0;
1014
1015 if (dev && dev->parent_bus) {
1016 char *d;
1017 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1018 if (dev->parent_bus->info->get_fw_dev_path) {
1019 d = dev->parent_bus->info->get_fw_dev_path(dev);
1020 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -05001021 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +02001022 } else {
1023 l += snprintf(p + l, size - l, "%s", dev->info->name);
1024 }
1025 }
1026 l += snprintf(p + l , size - l, "/");
1027
1028 return l;
1029}
1030
1031char* qdev_get_fw_dev_path(DeviceState *dev)
1032{
1033 char path[128];
1034 int l;
1035
1036 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1037
1038 path[l-1] = '\0';
1039
1040 return strdup(path);
1041}
Anthony Liguori85ed3032011-12-12 14:29:25 -06001042
Anthony Liguoricd34d662011-12-12 14:29:43 -06001043char *qdev_get_type(DeviceState *dev, Error **errp)
1044{
1045 return g_strdup(dev->info->name);
1046}
1047
Anthony Liguori85ed3032011-12-12 14:29:25 -06001048void qdev_ref(DeviceState *dev)
1049{
1050 dev->ref++;
1051}
1052
1053void qdev_unref(DeviceState *dev)
1054{
1055 g_assert(dev->ref > 0);
1056 dev->ref--;
1057}
Anthony Liguori44677de2011-12-12 14:29:26 -06001058
1059void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1060 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1061 DevicePropertyRelease *release,
1062 void *opaque, Error **errp)
1063{
1064 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1065
1066 prop->name = g_strdup(name);
1067 prop->type = g_strdup(type);
1068
1069 prop->get = get;
1070 prop->set = set;
1071 prop->release = release;
1072 prop->opaque = opaque;
1073
1074 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1075}
1076
1077static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1078{
1079 DeviceProperty *prop;
1080
1081 QTAILQ_FOREACH(prop, &dev->properties, node) {
1082 if (strcmp(prop->name, name) == 0) {
1083 return prop;
1084 }
1085 }
1086
1087 return NULL;
1088}
1089
1090void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1091 Error **errp)
1092{
1093 DeviceProperty *prop = qdev_property_find(dev, name);
1094
1095 if (prop == NULL) {
1096 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1097 return;
1098 }
1099
1100 if (!prop->get) {
1101 error_set(errp, QERR_PERMISSION_DENIED);
1102 } else {
1103 prop->get(dev, v, prop->opaque, name, errp);
1104 }
1105}
1106
1107void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1108 Error **errp)
1109{
1110 DeviceProperty *prop = qdev_property_find(dev, name);
1111
1112 if (prop == NULL) {
1113 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1114 return;
1115 }
1116
1117 if (!prop->set) {
1118 error_set(errp, QERR_PERMISSION_DENIED);
1119 } else {
Paolo Bonzini0d41d9a2011-12-18 17:05:05 +01001120 prop->set(dev, v, prop->opaque, name, errp);
Anthony Liguori44677de2011-12-12 14:29:26 -06001121 }
1122}
1123
1124const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1125{
1126 DeviceProperty *prop = qdev_property_find(dev, name);
1127
1128 if (prop == NULL) {
1129 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1130 return NULL;
1131 }
1132
1133 return prop->type;
1134}
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001135
1136/**
1137 * Legacy property handling
1138 */
1139
1140static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1141 const char *name, Error **errp)
1142{
1143 Property *prop = opaque;
1144
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001145 char buffer[1024];
1146 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001147
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001148 prop->info->print(dev, prop, buffer, sizeof(buffer));
1149 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001150}
1151
1152static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1153 const char *name, Error **errp)
1154{
1155 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001156 Error *local_err = NULL;
1157 char *ptr = NULL;
1158 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001159
1160 if (dev->state != DEV_STATE_CREATED) {
1161 error_set(errp, QERR_PERMISSION_DENIED);
1162 return;
1163 }
1164
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001165 visit_type_str(v, &ptr, name, &local_err);
1166 if (local_err) {
1167 error_propagate(errp, local_err);
1168 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001169 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001170
1171 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +01001172 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001173 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001174}
1175
1176/**
1177 * @qdev_add_legacy_property - adds a legacy property
1178 *
1179 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001180 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001181 *
1182 * Legacy properties are always processed as strings. The format of the string
1183 * depends on the property type.
1184 */
1185void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1186 Error **errp)
1187{
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001188 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001189
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001190 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +01001191 type = g_strdup_printf("legacy<%s>",
1192 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001193
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001194 qdev_property_add(dev, name, type,
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +01001195 prop->info->print ? qdev_get_legacy_property : NULL,
1196 prop->info->parse ? qdev_set_legacy_property : NULL,
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001197 NULL,
1198 prop, errp);
1199
1200 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +01001201 g_free(name);
1202}
1203
1204/**
1205 * @qdev_property_add_static - add a @Property to a device.
1206 *
1207 * Static properties access data in a struct. The actual type of the
1208 * property and the field depends on the property type.
1209 */
1210void qdev_property_add_static(DeviceState *dev, Property *prop,
1211 Error **errp)
1212{
1213 qdev_property_add(dev, prop->name, prop->info->name,
1214 prop->info->get, prop->info->set,
1215 NULL,
1216 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -06001217}
Anthony Liguoria10f07a2011-12-12 14:29:28 -06001218
1219DeviceState *qdev_get_root(void)
1220{
1221 static DeviceState *qdev_root;
1222
1223 if (!qdev_root) {
1224 qdev_root = qdev_create(NULL, "container");
1225 qdev_init_nofail(qdev_root);
1226 }
1227
1228 return qdev_root;
1229}
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001230
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001231static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1232 const char *name, Error **errp)
1233{
1234 DeviceState *child = opaque;
1235 gchar *path;
1236
1237 path = qdev_get_canonical_path(child);
1238 visit_type_str(v, &path, name, errp);
1239 g_free(path);
1240}
1241
1242void qdev_property_add_child(DeviceState *dev, const char *name,
1243 DeviceState *child, Error **errp)
1244{
1245 gchar *type;
1246
1247 type = g_strdup_printf("child<%s>", child->info->name);
1248
1249 qdev_property_add(dev, name, type, qdev_get_child_property,
1250 NULL, NULL, child, errp);
1251
1252 qdev_ref(child);
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001253 g_assert(child->parent == NULL);
1254 child->parent = dev;
Anthony Liguori3de1c3e2011-12-12 14:29:31 -06001255
1256 g_free(type);
1257}
1258
Anthony Liguori83e94fb2011-12-12 14:29:32 -06001259static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1260 const char *name, Error **errp)
1261{
1262 DeviceState **child = opaque;
1263 gchar *path;
1264
1265 if (*child) {
1266 path = qdev_get_canonical_path(*child);
1267 visit_type_str(v, &path, name, errp);
1268 g_free(path);
1269 } else {
1270 path = (gchar *)"";
1271 visit_type_str(v, &path, name, errp);
1272 }
1273}
1274
1275static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1276 const char *name, Error **errp)
1277{
1278 DeviceState **child = opaque;
1279 bool ambiguous = false;
1280 const char *type;
1281 char *path;
1282
1283 type = qdev_property_get_type(dev, name, NULL);
1284
1285 visit_type_str(v, &path, name, errp);
1286
1287 if (*child) {
1288 qdev_unref(*child);
1289 }
1290
1291 if (strcmp(path, "") != 0) {
1292 DeviceState *target;
1293
1294 target = qdev_resolve_path(path, &ambiguous);
1295 if (target) {
1296 gchar *target_type;
1297
1298 target_type = g_strdup_printf("link<%s>", target->info->name);
1299 if (strcmp(target_type, type) == 0) {
1300 *child = target;
1301 qdev_ref(target);
1302 } else {
1303 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1304 }
1305
1306 g_free(target_type);
1307 } else {
1308 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1309 }
1310 } else {
1311 *child = NULL;
1312 }
1313
1314 g_free(path);
1315}
1316
1317void qdev_property_add_link(DeviceState *dev, const char *name,
1318 const char *type, DeviceState **child,
1319 Error **errp)
1320{
1321 gchar *full_type;
1322
1323 full_type = g_strdup_printf("link<%s>", type);
1324
1325 qdev_property_add(dev, name, full_type,
1326 qdev_get_link_property,
1327 qdev_set_link_property,
1328 NULL, child, errp);
1329
1330 g_free(full_type);
1331}
1332
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001333gchar *qdev_get_canonical_path(DeviceState *dev)
1334{
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001335 DeviceState *root = qdev_get_root();
1336 char *newpath = NULL, *path = NULL;
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001337
Anthony Liguorib2b6c392011-12-12 14:29:40 -06001338 while (dev != root) {
1339 DeviceProperty *prop = NULL;
1340
1341 g_assert(dev->parent != NULL);
1342
1343 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1344 if (!strstart(prop->type, "child<", NULL)) {
1345 continue;
1346 }
1347
1348 if (prop->opaque == dev) {
1349 if (path) {
1350 newpath = g_strdup_printf("%s/%s", prop->name, path);
1351 g_free(path);
1352 path = newpath;
1353 } else {
1354 path = g_strdup(prop->name);
1355 }
1356 break;
1357 }
1358 }
1359
1360 g_assert(prop != NULL);
1361
1362 dev = dev->parent;
1363 }
Anthony Liguorif9fbd2f2011-12-12 14:29:29 -06001364
1365 newpath = g_strdup_printf("/%s", path);
1366 g_free(path);
1367
1368 return newpath;
1369}
Anthony Liguoridc45c212011-12-12 14:29:30 -06001370
1371static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1372 gchar **parts,
1373 int index)
1374{
1375 DeviceProperty *prop;
1376 DeviceState *child;
1377
1378 if (parts[index] == NULL) {
1379 return parent;
1380 }
1381
1382 if (strcmp(parts[index], "") == 0) {
1383 return qdev_resolve_abs_path(parent, parts, index + 1);
1384 }
1385
1386 prop = qdev_property_find(parent, parts[index]);
1387 if (prop == NULL) {
1388 return NULL;
1389 }
1390
1391 child = NULL;
1392 if (strstart(prop->type, "link<", NULL)) {
1393 DeviceState **pchild = prop->opaque;
1394 if (*pchild) {
1395 child = *pchild;
1396 }
1397 } else if (strstart(prop->type, "child<", NULL)) {
1398 child = prop->opaque;
1399 }
1400
1401 if (!child) {
1402 return NULL;
1403 }
1404
1405 return qdev_resolve_abs_path(child, parts, index + 1);
1406}
1407
1408static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1409 gchar **parts,
1410 bool *ambiguous)
1411{
1412 DeviceState *dev;
1413 DeviceProperty *prop;
1414
1415 dev = qdev_resolve_abs_path(parent, parts, 0);
1416
1417 QTAILQ_FOREACH(prop, &parent->properties, node) {
1418 DeviceState *found;
1419
1420 if (!strstart(prop->type, "child<", NULL)) {
1421 continue;
1422 }
1423
1424 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1425 if (found) {
1426 if (dev) {
1427 if (ambiguous) {
1428 *ambiguous = true;
1429 }
1430 return NULL;
1431 }
1432 dev = found;
1433 }
1434
1435 if (ambiguous && *ambiguous) {
1436 return NULL;
1437 }
1438 }
1439
1440 return dev;
1441}
1442
1443DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1444{
1445 bool partial_path = true;
1446 DeviceState *dev;
1447 gchar **parts;
1448
1449 parts = g_strsplit(path, "/", 0);
1450 if (parts == NULL || parts[0] == NULL) {
1451 g_strfreev(parts);
1452 return qdev_get_root();
1453 }
1454
1455 if (strcmp(parts[0], "") == 0) {
1456 partial_path = false;
1457 }
1458
1459 if (partial_path) {
1460 if (ambiguous) {
1461 *ambiguous = false;
1462 }
1463 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1464 } else {
1465 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1466 }
1467
1468 g_strfreev(parts);
1469
1470 return dev;
1471}
1472
Anthony Liguori6a146eb2011-12-12 14:29:42 -06001473typedef struct StringProperty
1474{
1475 char *(*get)(DeviceState *, Error **);
1476 void (*set)(DeviceState *, const char *, Error **);
1477} StringProperty;
1478
1479static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1480 const char *name, Error **errp)
1481{
1482 StringProperty *prop = opaque;
1483 char *value;
1484
1485 value = prop->get(dev, errp);
1486 if (value) {
1487 visit_type_str(v, &value, name, errp);
1488 g_free(value);
1489 }
1490}
1491
1492static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1493 const char *name, Error **errp)
1494{
1495 StringProperty *prop = opaque;
1496 char *value;
1497 Error *local_err = NULL;
1498
1499 visit_type_str(v, &value, name, &local_err);
1500 if (local_err) {
1501 error_propagate(errp, local_err);
1502 return;
1503 }
1504
1505 prop->set(dev, value, errp);
1506 g_free(value);
1507}
1508
1509static void qdev_property_release_str(DeviceState *dev, const char *name,
1510 void *opaque)
1511{
1512 StringProperty *prop = opaque;
1513 g_free(prop);
1514}
1515
1516void qdev_property_add_str(DeviceState *dev, const char *name,
1517 char *(*get)(DeviceState *, Error **),
1518 void (*set)(DeviceState *, const char *, Error **),
1519 Error **errp)
1520{
1521 StringProperty *prop = g_malloc0(sizeof(*prop));
1522
1523 prop->get = get;
1524 prop->set = set;
1525
1526 qdev_property_add(dev, name, "string",
1527 get ? qdev_property_get_str : NULL,
1528 set ? qdev_property_set_str : NULL,
1529 qdev_property_release_str,
1530 prop, errp);
1531}