blob: f0eb3a7384a1026ebfae3b36a249b232c561e04e [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"
31
Anthony Liguoriee46d8a2011-12-22 15:24:20 -060032int qdev_hotplug = 0;
Alex Williamson0ac8ef72011-01-04 12:37:50 -070033static bool qdev_hot_added = false;
34static bool qdev_hot_removed = false;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020035
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;
Isaku Yamahata2da8bb92011-08-02 10:59:13 +090038static void main_system_bus_create(void);
Paul Brook4d6ae672009-05-14 22:35:06 +010039
Paul Brookaae94602009-05-14 22:35:06 +010040/* Register a new device type. */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060041const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
42{
Anthony Liguori6e008582011-12-09 11:06:57 -060043 DeviceClass *dc = DEVICE_GET_CLASS(dev);
44 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060045}
46
47BusInfo *qdev_get_bus_info(DeviceState *dev)
48{
Anthony Liguori6e008582011-12-09 11:06:57 -060049 DeviceClass *dc = DEVICE_GET_CLASS(dev);
50 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060051}
52
53Property *qdev_get_props(DeviceState *dev)
54{
Anthony Liguori6e008582011-12-09 11:06:57 -060055 DeviceClass *dc = DEVICE_GET_CLASS(dev);
56 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060057}
58
59const char *qdev_fw_name(DeviceState *dev)
60{
Anthony Liguori6e008582011-12-09 11:06:57 -060061 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060062
Anthony Liguori6e008582011-12-09 11:06:57 -060063 if (dc->fw_name) {
64 return dc->fw_name;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060065 }
66
67 return object_get_typename(OBJECT(dev));
68}
69
Blue Swirla369da52011-09-27 19:15:42 +000070bool qdev_exists(const char *name)
71{
Anthony Liguori212ad112012-02-01 09:34:28 -060072 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +000073}
Anthony Liguori40021f02011-12-04 12:22:06 -060074
Paolo Bonzinica2cc782011-12-18 17:05:11 +010075static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
76 Error **errp);
77
Anthony Liguori9fbe6122011-12-22 15:14:27 -060078void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
Paul Brookaae94602009-05-14 22:35:06 +010079{
Anthony Liguoria5296ca2011-12-12 14:29:27 -060080 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010081
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020082 if (qdev_hotplug) {
83 assert(bus->allow_hotplug);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020084 }
Anthony Liguoria5296ca2011-12-12 14:29:27 -060085
Anthony Liguori9fbe6122011-12-22 15:14:27 -060086 dev->parent_bus = bus;
Anthony Liguori9674bfe2011-12-22 15:06:37 -060087 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060088
Anthony Liguori6e008582011-12-09 11:06:57 -060089 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -060090 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +010091 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060092 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +010093 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Paul Brookaae94602009-05-14 22:35:06 +010094}
95
Markus Armbruster0c175422010-02-19 19:12:18 +010096/* Create a new device. This only initializes the device state structure
97 and allows properties to be set. qdev_init should be called to
98 initialize the actual device emulation. */
99DeviceState *qdev_create(BusState *bus, const char *name)
100{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000101 DeviceState *dev;
102
103 dev = qdev_try_create(bus, name);
104 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100105 if (bus) {
106 hw_error("Unknown device '%s' for bus '%s'\n", name,
107 bus->info->name);
108 } else {
109 hw_error("Unknown device '%s' for default sysbus\n", name);
110 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000111 }
112
113 return dev;
114}
115
116DeviceState *qdev_try_create(BusState *bus, const char *name)
117{
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600118 DeviceState *dev;
119
120 dev = DEVICE(object_new(name));
121 if (!dev) {
122 return NULL;
123 }
124
Markus Armbruster0c175422010-02-19 19:12:18 +0100125 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100126 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100127 }
128
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600129 qdev_set_parent_bus(dev, bus);
130 qdev_prop_set_globals(dev);
131
132 return dev;
Markus Armbruster0c175422010-02-19 19:12:18 +0100133}
134
Paul Brookaae94602009-05-14 22:35:06 +0100135/* Initialize a device. Device properties should be set before calling
136 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200137 calling this function.
138 On failure, destroy the device and return negative value.
139 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200140int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100141{
Anthony Liguori6e008582011-12-09 11:06:57 -0600142 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200143 int rc;
144
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200145 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600146
Anthony Liguorid307af72011-12-09 15:02:56 -0600147 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200148 if (rc < 0) {
149 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200150 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200151 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600152 if (qdev_get_vmsd(dev)) {
153 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200154 dev->instance_id_alias,
155 dev->alias_required_for_version);
156 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200157 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600158 if (dev->hotplugged) {
159 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200160 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200161 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100162}
163
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200164void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
165 int required_for_version)
166{
167 assert(dev->state == DEV_STATE_CREATED);
168 dev->instance_id_alias = alias_id;
169 dev->alias_required_for_version = required_for_version;
170}
171
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200172int qdev_unplug(DeviceState *dev)
173{
Anthony Liguori6e008582011-12-09 11:06:57 -0600174 DeviceClass *dc = DEVICE_GET_CLASS(dev);
175
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200176 if (!dev->parent_bus->allow_hotplug) {
Markus Armbrustercc601cb2010-03-22 11:38:13 +0100177 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200178 return -1;
179 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600180 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530181
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700182 qdev_hot_removed = true;
183
Anthony Liguori6e008582011-12-09 11:06:57 -0600184 return dc->unplug(dev);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200185}
186
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900187static int qdev_reset_one(DeviceState *dev, void *opaque)
188{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600189 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900190
191 return 0;
192}
193
194BusState *sysbus_get_default(void)
195{
Stefan Weil68694892010-12-16 19:33:22 +0100196 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900197 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100198 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900199 return main_system_bus;
200}
201
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900202static int qbus_reset_one(BusState *bus, void *opaque)
203{
204 if (bus->info->reset) {
205 return bus->info->reset(bus);
206 }
207 return 0;
208}
209
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900210void qdev_reset_all(DeviceState *dev)
211{
212 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
213}
214
Isaku Yamahata80376c32010-12-20 14:33:35 +0900215void qbus_reset_all_fn(void *opaque)
216{
217 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200218 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900219}
220
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200221/* can be used as ->unplug() callback for the simple cases */
222int qdev_simple_unplug_cb(DeviceState *dev)
223{
224 /* just zap it */
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600225 object_unparent(OBJECT(dev));
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200226 qdev_free(dev);
227 return 0;
228}
229
Michael Tokarev3b29a102011-04-06 17:51:59 +0400230
231/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200232 returning an error value. This is okay during machine creation.
233 Don't use for hotplug, because there callers need to recover from
234 failure. Exception: if you know the device's init() callback can't
235 fail, then qdev_init_nofail() can't fail either, and is therefore
236 usable even then. But relying on the device implementation that
237 way is somewhat unclean, and best avoided. */
238void qdev_init_nofail(DeviceState *dev)
239{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200240 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600241 error_report("Initialization of device %s failed",
242 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200243 exit(1);
244 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200245}
246
Paul Brook02e2da42009-05-23 00:05:19 +0100247/* Unlink device from bus and free the structure. */
248void qdev_free(DeviceState *dev)
249{
Anthony Liguori32fea402011-12-16 14:34:46 -0600250 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100251}
252
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200253void qdev_machine_creation_done(void)
254{
255 /*
256 * ok, initial machine setup is done, starting from now we can
257 * only create hotpluggable devices
258 */
259 qdev_hotplug = 1;
260}
261
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700262bool qdev_machine_modified(void)
263{
264 return qdev_hot_added || qdev_hot_removed;
265}
266
Paul Brook02e2da42009-05-23 00:05:19 +0100267BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100268{
Paul Brook02e2da42009-05-23 00:05:19 +0100269 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100270}
271
Paul Brookaae94602009-05-14 22:35:06 +0100272void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
273{
274 assert(dev->num_gpio_in == 0);
275 dev->num_gpio_in = n;
276 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
277}
278
279void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
280{
281 assert(dev->num_gpio_out == 0);
282 dev->num_gpio_out = n;
283 dev->gpio_out = pins;
284}
285
286qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
287{
288 assert(n >= 0 && n < dev->num_gpio_in);
289 return dev->gpio_in[n];
290}
291
292void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
293{
294 assert(n >= 0 && n < dev->num_gpio_out);
295 dev->gpio_out[n] = pin;
296}
297
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200298void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
299{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200300 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200301 if (nd->vlan)
302 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
303 if (nd->netdev)
304 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530305 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200306 qdev_prop_exists(dev, "vectors")) {
307 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
308 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100309 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200310}
311
Paul Brook02e2da42009-05-23 00:05:19 +0100312BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100313{
Paul Brook02e2da42009-05-23 00:05:19 +0100314 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100315
Blue Swirl72cf2d42009-09-12 07:36:22 +0000316 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100317 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100318 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100319 }
320 }
321 return NULL;
322}
323
Anthony Liguori81699d82010-11-19 18:55:58 +0900324int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
325 qbus_walkerfn *busfn, void *opaque)
326{
327 DeviceState *dev;
328 int err;
329
330 if (busfn) {
331 err = busfn(bus, opaque);
332 if (err) {
333 return err;
334 }
335 }
336
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200337 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900338 err = qdev_walk_children(dev, devfn, busfn, opaque);
339 if (err < 0) {
340 return err;
341 }
342 }
343
344 return 0;
345}
346
347int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
348 qbus_walkerfn *busfn, void *opaque)
349{
350 BusState *bus;
351 int err;
352
353 if (devfn) {
354 err = devfn(dev, opaque);
355 if (err) {
356 return err;
357 }
358 }
359
360 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
361 err = qbus_walk_children(bus, devfn, busfn, opaque);
362 if (err < 0) {
363 return err;
364 }
365 }
366
367 return 0;
368}
369
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900370DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200371{
372 DeviceState *dev, *ret;
373 BusState *child;
374
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200375 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200376 if (dev->id && strcmp(dev->id, id) == 0)
377 return dev;
378 QLIST_FOREACH(child, &dev->child_bus, sibling) {
379 ret = qdev_find_recursive(child, id);
380 if (ret) {
381 return ret;
382 }
383 }
384 }
385 return NULL;
386}
387
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200388void qbus_create_inplace(BusState *bus, BusInfo *info,
389 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100390{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200391 char *buf;
392 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100393
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200394 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100395 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200396
397 if (name) {
398 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500399 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200400 } else if (parent && parent->id) {
401 /* parent device has id -> use it for bus name */
402 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500403 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200404 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
405 bus->name = buf;
406 } else {
407 /* no id -> use lowercase bus type for bus name */
408 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500409 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200410 len = snprintf(buf, len, "%s.%d", info->name,
411 parent ? parent->num_child_bus : 0);
412 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200413 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200414 bus->name = buf;
415 }
416
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200417 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100418 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000419 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200420 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900421 } else if (bus != main_system_bus) {
422 /* TODO: once all bus devices are qdevified,
423 only reset handler for main_system_bus should be registered here. */
424 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100425 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200426}
427
428BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
429{
430 BusState *bus;
431
Anthony Liguori7267c092011-08-20 22:09:37 -0500432 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200433 bus->qdev_allocated = 1;
434 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100435 return bus;
436}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100437
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900438static void main_system_bus_create(void)
439{
440 /* assign main_system_bus before qbus_create_inplace()
441 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500442 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900443 main_system_bus->qdev_allocated = 1;
444 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
445 "main-system-bus");
446}
447
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200448void qbus_free(BusState *bus)
449{
450 DeviceState *dev;
451
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200452 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200453 qdev_free(dev);
454 }
455 if (bus->parent) {
456 QLIST_REMOVE(bus, sibling);
457 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900458 } else {
459 assert(bus != main_system_bus); /* main_system_bus is never freed */
460 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200461 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500462 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200463 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500464 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200465 }
466}
467
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200468static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
469{
470 int l = 0;
471
472 if (dev && dev->parent_bus) {
473 char *d;
474 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
475 if (dev->parent_bus->info->get_fw_dev_path) {
476 d = dev->parent_bus->info->get_fw_dev_path(dev);
477 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500478 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200479 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600480 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200481 }
482 }
483 l += snprintf(p + l , size - l, "/");
484
485 return l;
486}
487
488char* qdev_get_fw_dev_path(DeviceState *dev)
489{
490 char path[128];
491 int l;
492
493 l = qdev_get_fw_dev_path_helper(dev, path, 128);
494
495 path[l-1] = '\0';
496
497 return strdup(path);
498}
Anthony Liguori85ed3032011-12-12 14:29:25 -0600499
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600500static char *qdev_get_type(Object *obj, Error **errp)
Anthony Liguoricd34d662011-12-12 14:29:43 -0600501{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600502 return g_strdup(object_get_typename(obj));
Anthony Liguori44677de2011-12-12 14:29:26 -0600503}
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600504
505/**
506 * Legacy property handling
507 */
508
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600509static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600510 const char *name, Error **errp)
511{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600512 DeviceState *dev = DEVICE(obj);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600513 Property *prop = opaque;
514
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100515 char buffer[1024];
516 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600517
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100518 prop->info->print(dev, prop, buffer, sizeof(buffer));
519 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600520}
521
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600522static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600523 const char *name, Error **errp)
524{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600525 DeviceState *dev = DEVICE(obj);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600526 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100527 Error *local_err = NULL;
528 char *ptr = NULL;
529 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600530
531 if (dev->state != DEV_STATE_CREATED) {
532 error_set(errp, QERR_PERMISSION_DENIED);
533 return;
534 }
535
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100536 visit_type_str(v, &ptr, name, &local_err);
537 if (local_err) {
538 error_propagate(errp, local_err);
539 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600540 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100541
542 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +0100543 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100544 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600545}
546
547/**
548 * @qdev_add_legacy_property - adds a legacy property
549 *
550 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100551 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600552 *
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100553 * Legacy properties are string versions of other OOM properties. The format
554 * of the string depends on the property type.
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600555 */
556void qdev_property_add_legacy(DeviceState *dev, Property *prop,
557 Error **errp)
558{
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100559 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600560
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100561 if (!prop->info->print && !prop->info->parse) {
562 return;
563 }
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100564 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100565 type = g_strdup_printf("legacy<%s>",
566 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600567
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600568 object_property_add(OBJECT(dev), name, type,
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100569 prop->info->print ? qdev_get_legacy_property : prop->info->get,
570 prop->info->parse ? qdev_set_legacy_property : prop->info->set,
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600571 NULL,
572 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600573
574 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100575 g_free(name);
576}
577
578/**
579 * @qdev_property_add_static - add a @Property to a device.
580 *
581 * Static properties access data in a struct. The actual type of the
582 * property and the field depends on the property type.
583 */
584void qdev_property_add_static(DeviceState *dev, Property *prop,
585 Error **errp)
586{
Paolo Bonzinid8229792012-02-02 09:47:13 +0100587 /*
588 * TODO qdev_prop_ptr does not have getters or setters. It must
589 * go now that it can be replaced with links. The test should be
590 * removed along with it: all static properties are read/write.
591 */
592 if (!prop->info->get && !prop->info->set) {
593 return;
594 }
595
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600596 object_property_add(OBJECT(dev), prop->name, prop->info->name,
597 prop->info->get, prop->info->set,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100598 prop->info->release,
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600599 prop, errp);
Anthony Liguori6a146eb2011-12-12 14:29:42 -0600600}
Anthony Liguori1de81d22011-12-19 16:37:46 -0600601
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600602static void device_initfn(Object *obj)
603{
604 DeviceState *dev = DEVICE(obj);
605 Property *prop;
606
607 if (qdev_hotplug) {
608 dev->hotplugged = 1;
609 qdev_hot_added = true;
610 }
611
612 dev->instance_id_alias = -1;
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600613 dev->state = DEV_STATE_CREATED;
614
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600615 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
616 qdev_property_add_legacy(dev, prop, NULL);
617 qdev_property_add_static(dev, prop, NULL);
618 }
619
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600620 object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +0100621 qdev_prop_set_defaults(dev, qdev_get_props(dev));
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600622}
623
Anthony Liguori60adba32011-12-23 08:38:56 -0600624/* Unlink device from bus and free the structure. */
625static void device_finalize(Object *obj)
626{
627 DeviceState *dev = DEVICE(obj);
628 BusState *bus;
Anthony Liguori60adba32011-12-23 08:38:56 -0600629 DeviceClass *dc = DEVICE_GET_CLASS(dev);
630
631 if (dev->state == DEV_STATE_INITIALIZED) {
632 while (dev->num_child_bus) {
633 bus = QLIST_FIRST(&dev->child_bus);
634 qbus_free(bus);
635 }
636 if (qdev_get_vmsd(dev)) {
637 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
638 }
639 if (dc->exit) {
640 dc->exit(dev);
641 }
642 if (dev->opts) {
643 qemu_opts_del(dev->opts);
644 }
645 }
646 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori60adba32011-12-23 08:38:56 -0600647}
648
Anthony Liguori94afdad2011-12-04 11:36:01 -0600649void device_reset(DeviceState *dev)
650{
651 DeviceClass *klass = DEVICE_GET_CLASS(dev);
652
653 if (klass->reset) {
654 klass->reset(dev);
655 }
656}
657
Anthony Liguori32fea402011-12-16 14:34:46 -0600658static TypeInfo device_type_info = {
659 .name = TYPE_DEVICE,
660 .parent = TYPE_OBJECT,
661 .instance_size = sizeof(DeviceState),
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600662 .instance_init = device_initfn,
Anthony Liguori60adba32011-12-23 08:38:56 -0600663 .instance_finalize = device_finalize,
Anthony Liguori32fea402011-12-16 14:34:46 -0600664 .abstract = true,
665 .class_size = sizeof(DeviceClass),
666};
667
Andreas Färber83f7d432012-02-09 15:20:55 +0100668static void qdev_register_types(void)
Anthony Liguori32fea402011-12-16 14:34:46 -0600669{
670 type_register_static(&device_type_info);
671}
672
Andreas Färber83f7d432012-02-09 15:20:55 +0100673type_init(qdev_register_types)