blob: 0bcde20c92a39cf4f43a1cdeb1eeaf907e164c9e [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"
Luiz Capitulino56f91072012-03-14 17:37:38 -030031#include "error.h"
Paul Brookaae94602009-05-14 22:35:06 +010032
Anthony Liguoriee46d8a2011-12-22 15:24:20 -060033int 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
Paul Brookaae94602009-05-14 22:35:06 +010041/* Register a new device type. */
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060042const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
43{
Anthony Liguori6e008582011-12-09 11:06:57 -060044 DeviceClass *dc = DEVICE_GET_CLASS(dev);
45 return dc->vmsd;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060046}
47
48BusInfo *qdev_get_bus_info(DeviceState *dev)
49{
Anthony Liguori6e008582011-12-09 11:06:57 -060050 DeviceClass *dc = DEVICE_GET_CLASS(dev);
51 return dc->bus_info;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060052}
53
54Property *qdev_get_props(DeviceState *dev)
55{
Anthony Liguori6e008582011-12-09 11:06:57 -060056 DeviceClass *dc = DEVICE_GET_CLASS(dev);
57 return dc->props;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060058}
59
60const char *qdev_fw_name(DeviceState *dev)
61{
Anthony Liguori6e008582011-12-09 11:06:57 -060062 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060063
Anthony Liguori6e008582011-12-09 11:06:57 -060064 if (dc->fw_name) {
65 return dc->fw_name;
Anthony Liguori4be9f0d2011-12-09 10:51:49 -060066 }
67
68 return object_get_typename(OBJECT(dev));
69}
70
Blue Swirla369da52011-09-27 19:15:42 +000071bool qdev_exists(const char *name)
72{
Anthony Liguori212ad112012-02-01 09:34:28 -060073 return !!object_class_by_name(name);
Blue Swirla369da52011-09-27 19:15:42 +000074}
Anthony Liguori40021f02011-12-04 12:22:06 -060075
Paolo Bonzinica2cc782011-12-18 17:05:11 +010076static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
77 Error **errp);
78
Anthony Liguori9fbe6122011-12-22 15:14:27 -060079void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
Paul Brookaae94602009-05-14 22:35:06 +010080{
Anthony Liguoria5296ca2011-12-12 14:29:27 -060081 Property *prop;
Paul Brookaae94602009-05-14 22:35:06 +010082
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020083 if (qdev_hotplug) {
84 assert(bus->allow_hotplug);
Gerd Hoffmann3418bd22009-09-25 21:42:41 +020085 }
Anthony Liguoria5296ca2011-12-12 14:29:27 -060086
Anthony Liguori9fbe6122011-12-22 15:14:27 -060087 dev->parent_bus = bus;
Anthony Liguori9674bfe2011-12-22 15:06:37 -060088 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060089
Anthony Liguori6e008582011-12-09 11:06:57 -060090 for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) {
Anthony Liguoria5296ca2011-12-12 14:29:27 -060091 qdev_property_add_legacy(dev, prop, NULL);
Paolo Bonzinica2cc782011-12-18 17:05:11 +010092 qdev_property_add_static(dev, prop, NULL);
Anthony Liguoria5296ca2011-12-12 14:29:27 -060093 }
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +010094 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
Paul Brookaae94602009-05-14 22:35:06 +010095}
96
Markus Armbruster0c175422010-02-19 19:12:18 +010097/* Create a new device. This only initializes the device state structure
98 and allows properties to be set. qdev_init should be called to
99 initialize the actual device emulation. */
100DeviceState *qdev_create(BusState *bus, const char *name)
101{
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000102 DeviceState *dev;
103
104 dev = qdev_try_create(bus, name);
105 if (!dev) {
Peter Maydelle92714c2011-08-03 23:49:04 +0100106 if (bus) {
107 hw_error("Unknown device '%s' for bus '%s'\n", name,
108 bus->info->name);
109 } else {
110 hw_error("Unknown device '%s' for default sysbus\n", name);
111 }
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000112 }
113
114 return dev;
115}
116
Paolo Bonzinida57feb2012-03-27 18:38:47 +0200117DeviceState *qdev_try_create(BusState *bus, const char *type)
Blue Swirl0bcdeda2011-02-05 14:34:25 +0000118{
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600119 DeviceState *dev;
120
Paolo Bonzinida57feb2012-03-27 18:38:47 +0200121 if (object_class_by_name(type) == NULL) {
Andreas Färber4ed658c2012-02-17 02:47:44 +0100122 return NULL;
123 }
Paolo Bonzinida57feb2012-03-27 18:38:47 +0200124 dev = DEVICE(object_new(type));
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600125 if (!dev) {
126 return NULL;
127 }
128
Markus Armbruster0c175422010-02-19 19:12:18 +0100129 if (!bus) {
Stefan Weil68694892010-12-16 19:33:22 +0100130 bus = sysbus_get_default();
Markus Armbruster0c175422010-02-19 19:12:18 +0100131 }
132
Anthony Liguori9fbe6122011-12-22 15:14:27 -0600133 qdev_set_parent_bus(dev, bus);
134 qdev_prop_set_globals(dev);
135
136 return dev;
Markus Armbruster0c175422010-02-19 19:12:18 +0100137}
138
Paul Brookaae94602009-05-14 22:35:06 +0100139/* Initialize a device. Device properties should be set before calling
140 this function. IRQs and MMIO regions should be connected/mapped after
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200141 calling this function.
142 On failure, destroy the device and return negative value.
143 Return 0 on success. */
Gerd Hoffmann81a322d2009-08-14 10:36:05 +0200144int qdev_init(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100145{
Anthony Liguori6e008582011-12-09 11:06:57 -0600146 DeviceClass *dc = DEVICE_GET_CLASS(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200147 int rc;
148
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200149 assert(dev->state == DEV_STATE_CREATED);
Anthony Liguori6e008582011-12-09 11:06:57 -0600150
Anthony Liguorid307af72011-12-09 15:02:56 -0600151 rc = dc->init(dev);
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200152 if (rc < 0) {
153 qdev_free(dev);
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200154 return rc;
Markus Armbruster18cfeb52009-10-07 01:15:56 +0200155 }
Paolo Bonzinida57feb2012-03-27 18:38:47 +0200156
157 if (!OBJECT(dev)->parent) {
158 static int unattached_count = 0;
159 gchar *name = g_strdup_printf("device[%d]", unattached_count++);
160
Andreas Färberdfe47e72012-04-05 13:21:46 +0200161 object_property_add_child(container_get(qdev_get_machine(),
162 "/unattached"),
163 name, OBJECT(dev), NULL);
Paolo Bonzinida57feb2012-03-27 18:38:47 +0200164 g_free(name);
165 }
166
Anthony Liguori6e008582011-12-09 11:06:57 -0600167 if (qdev_get_vmsd(dev)) {
168 vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200169 dev->instance_id_alias,
170 dev->alias_required_for_version);
171 }
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200172 dev->state = DEV_STATE_INITIALIZED;
Anthony Liguori94afdad2011-12-04 11:36:01 -0600173 if (dev->hotplugged) {
174 device_reset(dev);
Jan Kiszka5ab28c82011-07-24 19:38:36 +0200175 }
Gerd Hoffmann959f7332009-09-01 09:56:12 +0200176 return 0;
Paul Brook02e2da42009-05-23 00:05:19 +0100177}
178
Jan Kiszka4d2ffa02010-05-15 13:32:40 +0200179void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
180 int required_for_version)
181{
182 assert(dev->state == DEV_STATE_CREATED);
183 dev->instance_id_alias = alias_id;
184 dev->alias_required_for_version = required_for_version;
185}
186
Luiz Capitulino56f91072012-03-14 17:37:38 -0300187void qdev_unplug(DeviceState *dev, Error **errp)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200188{
Anthony Liguori6e008582011-12-09 11:06:57 -0600189 DeviceClass *dc = DEVICE_GET_CLASS(dev);
190
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200191 if (!dev->parent_bus->allow_hotplug) {
Luiz Capitulino56f91072012-03-14 17:37:38 -0300192 error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
193 return;
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200194 }
Anthony Liguori6e008582011-12-09 11:06:57 -0600195 assert(dc->unplug != NULL);
Amit Shah593831d2009-11-02 14:56:41 +0530196
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700197 qdev_hot_removed = true;
198
Luiz Capitulino56f91072012-03-14 17:37:38 -0300199 if (dc->unplug(dev) < 0) {
200 error_set(errp, QERR_UNDEFINED_ERROR);
201 return;
202 }
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200203}
204
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900205static int qdev_reset_one(DeviceState *dev, void *opaque)
206{
Anthony Liguori94afdad2011-12-04 11:36:01 -0600207 device_reset(dev);
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900208
209 return 0;
210}
211
212BusState *sysbus_get_default(void)
213{
Stefan Weil68694892010-12-16 19:33:22 +0100214 if (!main_system_bus) {
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900215 main_system_bus_create();
Stefan Weil68694892010-12-16 19:33:22 +0100216 }
Anthony Liguoriec990eb2010-11-19 18:55:59 +0900217 return main_system_bus;
218}
219
Isaku Yamahatab4694b72010-11-19 18:56:00 +0900220static int qbus_reset_one(BusState *bus, void *opaque)
221{
222 if (bus->info->reset) {
223 return bus->info->reset(bus);
224 }
225 return 0;
226}
227
Isaku Yamahata5af0a042010-11-19 18:56:01 +0900228void qdev_reset_all(DeviceState *dev)
229{
230 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
231}
232
Isaku Yamahata80376c32010-12-20 14:33:35 +0900233void qbus_reset_all_fn(void *opaque)
234{
235 BusState *bus = opaque;
Michael S. Tsirkinf530cce2010-12-20 15:17:10 +0200236 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
Isaku Yamahata80376c32010-12-20 14:33:35 +0900237}
238
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200239/* can be used as ->unplug() callback for the simple cases */
240int qdev_simple_unplug_cb(DeviceState *dev)
241{
242 /* just zap it */
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600243 object_unparent(OBJECT(dev));
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200244 qdev_free(dev);
245 return 0;
246}
247
Michael Tokarev3b29a102011-04-06 17:51:59 +0400248
249/* Like qdev_init(), but terminate program via error_report() instead of
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200250 returning an error value. This is okay during machine creation.
251 Don't use for hotplug, because there callers need to recover from
252 failure. Exception: if you know the device's init() callback can't
253 fail, then qdev_init_nofail() can't fail either, and is therefore
254 usable even then. But relying on the device implementation that
255 way is somewhat unclean, and best avoided. */
256void qdev_init_nofail(DeviceState *dev)
257{
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200258 if (qdev_init(dev) < 0) {
Anthony Liguori6e008582011-12-09 11:06:57 -0600259 error_report("Initialization of device %s failed",
260 object_get_typename(OBJECT(dev)));
Markus Armbrusterbd6c9a62010-05-27 21:23:08 +0200261 exit(1);
262 }
Markus Armbrustere23a1b32009-10-07 01:15:58 +0200263}
264
Paul Brook02e2da42009-05-23 00:05:19 +0100265/* Unlink device from bus and free the structure. */
266void qdev_free(DeviceState *dev)
267{
Anthony Liguori32fea402011-12-16 14:34:46 -0600268 object_delete(OBJECT(dev));
Paul Brookaae94602009-05-14 22:35:06 +0100269}
270
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200271void qdev_machine_creation_done(void)
272{
273 /*
274 * ok, initial machine setup is done, starting from now we can
275 * only create hotpluggable devices
276 */
277 qdev_hotplug = 1;
278}
279
Alex Williamson0ac8ef72011-01-04 12:37:50 -0700280bool qdev_machine_modified(void)
281{
282 return qdev_hot_added || qdev_hot_removed;
283}
284
Paul Brook02e2da42009-05-23 00:05:19 +0100285BusState *qdev_get_parent_bus(DeviceState *dev)
Paul Brookaae94602009-05-14 22:35:06 +0100286{
Paul Brook02e2da42009-05-23 00:05:19 +0100287 return dev->parent_bus;
Paul Brookaae94602009-05-14 22:35:06 +0100288}
289
Paul Brookaae94602009-05-14 22:35:06 +0100290void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
291{
292 assert(dev->num_gpio_in == 0);
293 dev->num_gpio_in = n;
294 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
295}
296
297void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
298{
299 assert(dev->num_gpio_out == 0);
300 dev->num_gpio_out = n;
301 dev->gpio_out = pins;
302}
303
304qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
305{
306 assert(n >= 0 && n < dev->num_gpio_in);
307 return dev->gpio_in[n];
308}
309
310void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
311{
312 assert(n >= 0 && n < dev->num_gpio_out);
313 dev->gpio_out[n] = pin;
314}
315
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200316void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
317{
Jan Kiszka6eed1852011-07-20 12:20:22 +0200318 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200319 if (nd->vlan)
320 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
321 if (nd->netdev)
322 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
Amit Shah75422b02010-02-25 17:24:43 +0530323 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
Gerd Hoffmann97b15622009-10-21 15:25:35 +0200324 qdev_prop_exists(dev, "vectors")) {
325 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
326 }
Peter Maydell48e2faf2011-05-20 16:50:01 +0100327 nd->instantiated = 1;
Gerd Hoffmanned16ab52009-10-21 15:25:26 +0200328}
329
Paul Brook02e2da42009-05-23 00:05:19 +0100330BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
Paul Brook4d6ae672009-05-14 22:35:06 +0100331{
Paul Brook02e2da42009-05-23 00:05:19 +0100332 BusState *bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100333
Blue Swirl72cf2d42009-09-12 07:36:22 +0000334 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
Paul Brook4d6ae672009-05-14 22:35:06 +0100335 if (strcmp(name, bus->name) == 0) {
Paul Brook02e2da42009-05-23 00:05:19 +0100336 return bus;
Paul Brook4d6ae672009-05-14 22:35:06 +0100337 }
338 }
339 return NULL;
340}
341
Anthony Liguori81699d82010-11-19 18:55:58 +0900342int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
343 qbus_walkerfn *busfn, void *opaque)
344{
345 DeviceState *dev;
346 int err;
347
348 if (busfn) {
349 err = busfn(bus, opaque);
350 if (err) {
351 return err;
352 }
353 }
354
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200355 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Anthony Liguori81699d82010-11-19 18:55:58 +0900356 err = qdev_walk_children(dev, devfn, busfn, opaque);
357 if (err < 0) {
358 return err;
359 }
360 }
361
362 return 0;
363}
364
365int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
366 qbus_walkerfn *busfn, void *opaque)
367{
368 BusState *bus;
369 int err;
370
371 if (devfn) {
372 err = devfn(dev, opaque);
373 if (err) {
374 return err;
375 }
376 }
377
378 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
379 err = qbus_walk_children(bus, devfn, busfn, opaque);
380 if (err < 0) {
381 return err;
382 }
383 }
384
385 return 0;
386}
387
Isaku Yamahataa2ee6b42010-12-24 12:14:12 +0900388DeviceState *qdev_find_recursive(BusState *bus, const char *id)
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200389{
390 DeviceState *dev, *ret;
391 BusState *child;
392
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200393 QTAILQ_FOREACH(dev, &bus->children, sibling) {
Gerd Hoffmann3418bd22009-09-25 21:42:41 +0200394 if (dev->id && strcmp(dev->id, id) == 0)
395 return dev;
396 QLIST_FOREACH(child, &dev->child_bus, sibling) {
397 ret = qdev_find_recursive(child, id);
398 if (ret) {
399 return ret;
400 }
401 }
402 }
403 return NULL;
404}
405
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200406void qbus_create_inplace(BusState *bus, BusInfo *info,
407 DeviceState *parent, const char *name)
Paul Brook02e2da42009-05-23 00:05:19 +0100408{
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200409 char *buf;
410 int i,len;
Paul Brook02e2da42009-05-23 00:05:19 +0100411
Gerd Hoffmann10c4c982009-06-30 14:12:08 +0200412 bus->info = info;
Paul Brook02e2da42009-05-23 00:05:19 +0100413 bus->parent = parent;
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200414
415 if (name) {
416 /* use supplied name */
Anthony Liguori7267c092011-08-20 22:09:37 -0500417 bus->name = g_strdup(name);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200418 } else if (parent && parent->id) {
419 /* parent device has id -> use it for bus name */
420 len = strlen(parent->id) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500421 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200422 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
423 bus->name = buf;
424 } else {
425 /* no id -> use lowercase bus type for bus name */
426 len = strlen(info->name) + 16;
Anthony Liguori7267c092011-08-20 22:09:37 -0500427 buf = g_malloc(len);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200428 len = snprintf(buf, len, "%s.%d", info->name,
429 parent ? parent->num_child_bus : 0);
430 for (i = 0; i < len; i++)
Christoph Eggerbb87ece2009-07-30 15:28:45 +0200431 buf[i] = qemu_tolower(buf[i]);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200432 bus->name = buf;
433 }
434
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200435 QTAILQ_INIT(&bus->children);
Paul Brook02e2da42009-05-23 00:05:19 +0100436 if (parent) {
Blue Swirl72cf2d42009-09-12 07:36:22 +0000437 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
Gerd Hoffmannd271de92009-07-15 13:59:24 +0200438 parent->num_child_bus++;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900439 } else if (bus != main_system_bus) {
440 /* TODO: once all bus devices are qdevified,
441 only reset handler for main_system_bus should be registered here. */
442 qemu_register_reset(qbus_reset_all_fn, bus);
Paul Brook02e2da42009-05-23 00:05:19 +0100443 }
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200444}
445
446BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
447{
448 BusState *bus;
449
Anthony Liguori7267c092011-08-20 22:09:37 -0500450 bus = g_malloc0(info->size);
Gerd Hoffmanncd739fb2009-09-16 22:25:27 +0200451 bus->qdev_allocated = 1;
452 qbus_create_inplace(bus, info, parent, name);
Paul Brook02e2da42009-05-23 00:05:19 +0100453 return bus;
454}
Gerd Hoffmanncae49562009-06-05 15:53:17 +0100455
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900456static void main_system_bus_create(void)
457{
458 /* assign main_system_bus before qbus_create_inplace()
459 * in order to make "if (bus != main_system_bus)" work */
Anthony Liguori7267c092011-08-20 22:09:37 -0500460 main_system_bus = g_malloc0(system_bus_info.size);
Isaku Yamahata2da8bb92011-08-02 10:59:13 +0900461 main_system_bus->qdev_allocated = 1;
462 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
463 "main-system-bus");
464}
465
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200466void qbus_free(BusState *bus)
467{
468 DeviceState *dev;
469
Paolo Bonzinid8bb00d2011-09-14 09:28:06 +0200470 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200471 qdev_free(dev);
472 }
473 if (bus->parent) {
474 QLIST_REMOVE(bus, sibling);
475 bus->parent->num_child_bus--;
Isaku Yamahata80376c32010-12-20 14:33:35 +0900476 } else {
477 assert(bus != main_system_bus); /* main_system_bus is never freed */
478 qemu_unregister_reset(qbus_reset_all_fn, bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200479 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500480 g_free((void*)bus->name);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200481 if (bus->qdev_allocated) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500482 g_free(bus);
Gerd Hoffmann131ec1b2009-09-25 21:42:34 +0200483 }
484}
485
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200486static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
487{
488 int l = 0;
489
490 if (dev && dev->parent_bus) {
491 char *d;
492 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
493 if (dev->parent_bus->info->get_fw_dev_path) {
494 d = dev->parent_bus->info->get_fw_dev_path(dev);
495 l += snprintf(p + l, size - l, "%s", d);
Anthony Liguori7267c092011-08-20 22:09:37 -0500496 g_free(d);
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200497 } else {
Anthony Liguorif79f2bf2011-12-04 11:17:51 -0600498 l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
Gleb Natapov1ca4d092010-12-08 13:35:05 +0200499 }
500 }
501 l += snprintf(p + l , size - l, "/");
502
503 return l;
504}
505
506char* qdev_get_fw_dev_path(DeviceState *dev)
507{
508 char path[128];
509 int l;
510
511 l = qdev_get_fw_dev_path_helper(dev, path, 128);
512
513 path[l-1] = '\0';
514
515 return strdup(path);
516}
Anthony Liguori85ed3032011-12-12 14:29:25 -0600517
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600518static char *qdev_get_type(Object *obj, Error **errp)
Anthony Liguoricd34d662011-12-12 14:29:43 -0600519{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600520 return g_strdup(object_get_typename(obj));
Anthony Liguori44677de2011-12-12 14:29:26 -0600521}
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600522
523/**
524 * Legacy property handling
525 */
526
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600527static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600528 const char *name, Error **errp)
529{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600530 DeviceState *dev = DEVICE(obj);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600531 Property *prop = opaque;
532
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100533 char buffer[1024];
534 char *ptr = buffer;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600535
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100536 prop->info->print(dev, prop, buffer, sizeof(buffer));
537 visit_type_str(v, &ptr, name, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600538}
539
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600540static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600541 const char *name, Error **errp)
542{
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600543 DeviceState *dev = DEVICE(obj);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600544 Property *prop = opaque;
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100545 Error *local_err = NULL;
546 char *ptr = NULL;
547 int ret;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600548
549 if (dev->state != DEV_STATE_CREATED) {
550 error_set(errp, QERR_PERMISSION_DENIED);
551 return;
552 }
553
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100554 visit_type_str(v, &ptr, name, &local_err);
555 if (local_err) {
556 error_propagate(errp, local_err);
557 return;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600558 }
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100559
560 ret = prop->info->parse(dev, prop, ptr);
Paolo Bonzini7db4c4e2011-12-18 17:05:07 +0100561 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
Paolo Bonzinie3cb6ba2011-12-18 17:05:06 +0100562 g_free(ptr);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600563}
564
565/**
566 * @qdev_add_legacy_property - adds a legacy property
567 *
568 * Do not use this is new code! Properties added through this interface will
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100569 * be given names and types in the "legacy" namespace.
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600570 *
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100571 * Legacy properties are string versions of other OOM properties. The format
572 * of the string depends on the property type.
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600573 */
574void qdev_property_add_legacy(DeviceState *dev, Property *prop,
575 Error **errp)
576{
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100577 gchar *name, *type;
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600578
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100579 if (!prop->info->print && !prop->info->parse) {
580 return;
581 }
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100582 name = g_strdup_printf("legacy-%s", prop->name);
Paolo Bonzinicafe5bd2011-12-18 17:05:10 +0100583 type = g_strdup_printf("legacy<%s>",
584 prop->info->legacy_name ?: prop->info->name);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600585
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600586 object_property_add(OBJECT(dev), name, type,
Paolo Bonzini68ee3562012-02-02 10:17:19 +0100587 prop->info->print ? qdev_get_legacy_property : prop->info->get,
588 prop->info->parse ? qdev_set_legacy_property : prop->info->set,
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600589 NULL,
590 prop, errp);
Anthony Liguoria5296ca2011-12-12 14:29:27 -0600591
592 g_free(type);
Paolo Bonzinica2cc782011-12-18 17:05:11 +0100593 g_free(name);
594}
595
596/**
597 * @qdev_property_add_static - add a @Property to a device.
598 *
599 * Static properties access data in a struct. The actual type of the
600 * property and the field depends on the property type.
601 */
602void qdev_property_add_static(DeviceState *dev, Property *prop,
603 Error **errp)
604{
Paolo Bonzinid8229792012-02-02 09:47:13 +0100605 /*
606 * TODO qdev_prop_ptr does not have getters or setters. It must
607 * go now that it can be replaced with links. The test should be
608 * removed along with it: all static properties are read/write.
609 */
610 if (!prop->info->get && !prop->info->set) {
611 return;
612 }
613
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600614 object_property_add(OBJECT(dev), prop->name, prop->info->name,
615 prop->info->get, prop->info->set,
Paolo Bonzinidd0ba252012-02-02 13:08:48 +0100616 prop->info->release,
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600617 prop, errp);
Anthony Liguori6a146eb2011-12-12 14:29:42 -0600618}
Anthony Liguori1de81d22011-12-19 16:37:46 -0600619
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600620static void device_initfn(Object *obj)
621{
622 DeviceState *dev = DEVICE(obj);
623 Property *prop;
624
625 if (qdev_hotplug) {
626 dev->hotplugged = 1;
627 qdev_hot_added = true;
628 }
629
630 dev->instance_id_alias = -1;
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600631 dev->state = DEV_STATE_CREATED;
632
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600633 for (prop = qdev_get_props(dev); prop && prop->name; prop++) {
634 qdev_property_add_legacy(dev, prop, NULL);
635 qdev_property_add_static(dev, prop, NULL);
636 }
637
Anthony Liguori57c9faf2012-01-30 08:55:55 -0600638 object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL);
Paolo Bonzini4f2d3d72012-02-02 09:43:02 +0100639 qdev_prop_set_defaults(dev, qdev_get_props(dev));
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600640}
641
Anthony Liguori60adba32011-12-23 08:38:56 -0600642/* Unlink device from bus and free the structure. */
643static void device_finalize(Object *obj)
644{
645 DeviceState *dev = DEVICE(obj);
646 BusState *bus;
Anthony Liguori60adba32011-12-23 08:38:56 -0600647 DeviceClass *dc = DEVICE_GET_CLASS(dev);
648
649 if (dev->state == DEV_STATE_INITIALIZED) {
650 while (dev->num_child_bus) {
651 bus = QLIST_FIRST(&dev->child_bus);
652 qbus_free(bus);
653 }
654 if (qdev_get_vmsd(dev)) {
655 vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
656 }
657 if (dc->exit) {
658 dc->exit(dev);
659 }
660 if (dev->opts) {
661 qemu_opts_del(dev->opts);
662 }
663 }
664 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
Anthony Liguori60adba32011-12-23 08:38:56 -0600665}
666
Anthony Liguori94afdad2011-12-04 11:36:01 -0600667void device_reset(DeviceState *dev)
668{
669 DeviceClass *klass = DEVICE_GET_CLASS(dev);
670
671 if (klass->reset) {
672 klass->reset(dev);
673 }
674}
675
Paolo Bonzinif05f6b42012-03-28 16:34:12 +0200676Object *qdev_get_machine(void)
677{
678 static Object *dev;
679
680 if (dev == NULL) {
Andreas Färberdfe47e72012-04-05 13:21:46 +0200681 dev = container_get(object_get_root(), "/machine");
Paolo Bonzinif05f6b42012-03-28 16:34:12 +0200682 }
683
684 return dev;
685}
686
Anthony Liguori32fea402011-12-16 14:34:46 -0600687static TypeInfo device_type_info = {
688 .name = TYPE_DEVICE,
689 .parent = TYPE_OBJECT,
690 .instance_size = sizeof(DeviceState),
Anthony Liguori9674bfe2011-12-22 15:06:37 -0600691 .instance_init = device_initfn,
Anthony Liguori60adba32011-12-23 08:38:56 -0600692 .instance_finalize = device_finalize,
Anthony Liguori32fea402011-12-16 14:34:46 -0600693 .abstract = true,
694 .class_size = sizeof(DeviceClass),
695};
696
Andreas Färber83f7d432012-02-09 15:20:55 +0100697static void qdev_register_types(void)
Anthony Liguori32fea402011-12-16 14:34:46 -0600698{
699 type_register_static(&device_type_info);
700}
701
Andreas Färber83f7d432012-02-09 15:20:55 +0100702type_init(qdev_register_types)