1a62c8911SAndreas Färber /* 2a62c8911SAndreas Färber * Dynamic device configuration and creation -- buses. 3a62c8911SAndreas Färber * 4a62c8911SAndreas Färber * Copyright (c) 2009 CodeSourcery 5a62c8911SAndreas Färber * 6a62c8911SAndreas Färber * This library is free software; you can redistribute it and/or 7a62c8911SAndreas Färber * modify it under the terms of the GNU Lesser General Public 8a62c8911SAndreas Färber * License as published by the Free Software Foundation; either 9a62c8911SAndreas Färber * version 2 of the License, or (at your option) any later version. 10a62c8911SAndreas Färber * 11a62c8911SAndreas Färber * This library is distributed in the hope that it will be useful, 12a62c8911SAndreas Färber * but WITHOUT ANY WARRANTY; without even the implied warranty of 13a62c8911SAndreas Färber * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14a62c8911SAndreas Färber * Lesser General Public License for more details. 15a62c8911SAndreas Färber * 16a62c8911SAndreas Färber * You should have received a copy of the GNU Lesser General Public 17a62c8911SAndreas Färber * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18a62c8911SAndreas Färber */ 19a62c8911SAndreas Färber 20a62c8911SAndreas Färber #include "qemu/osdep.h" 21856dfd8aSMarkus Armbruster #include "qemu/ctype.h" 22*0b8fa32fSMarkus Armbruster #include "qemu/module.h" 23a62c8911SAndreas Färber #include "hw/qdev.h" 24a62c8911SAndreas Färber #include "qapi/error.h" 25a62c8911SAndreas Färber 2694d1cc5fSMichael Roth void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp) 27a62c8911SAndreas Färber { 28a62c8911SAndreas Färber object_property_set_link(OBJECT(bus), OBJECT(handler), 29a62c8911SAndreas Färber QDEV_HOTPLUG_HANDLER_PROPERTY, errp); 30a62c8911SAndreas Färber } 31a62c8911SAndreas Färber 32a62c8911SAndreas Färber void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp) 33a62c8911SAndreas Färber { 3494d1cc5fSMichael Roth qbus_set_hotplug_handler(bus, OBJECT(bus), errp); 35a62c8911SAndreas Färber } 36a62c8911SAndreas Färber 37a62c8911SAndreas Färber int qbus_walk_children(BusState *bus, 38a62c8911SAndreas Färber qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, 39a62c8911SAndreas Färber qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, 40a62c8911SAndreas Färber void *opaque) 41a62c8911SAndreas Färber { 42a62c8911SAndreas Färber BusChild *kid; 43a62c8911SAndreas Färber int err; 44a62c8911SAndreas Färber 45a62c8911SAndreas Färber if (pre_busfn) { 46a62c8911SAndreas Färber err = pre_busfn(bus, opaque); 47a62c8911SAndreas Färber if (err) { 48a62c8911SAndreas Färber return err; 49a62c8911SAndreas Färber } 50a62c8911SAndreas Färber } 51a62c8911SAndreas Färber 52a62c8911SAndreas Färber QTAILQ_FOREACH(kid, &bus->children, sibling) { 53a62c8911SAndreas Färber err = qdev_walk_children(kid->child, 54a62c8911SAndreas Färber pre_devfn, pre_busfn, 55a62c8911SAndreas Färber post_devfn, post_busfn, opaque); 56a62c8911SAndreas Färber if (err < 0) { 57a62c8911SAndreas Färber return err; 58a62c8911SAndreas Färber } 59a62c8911SAndreas Färber } 60a62c8911SAndreas Färber 61a62c8911SAndreas Färber if (post_busfn) { 62a62c8911SAndreas Färber err = post_busfn(bus, opaque); 63a62c8911SAndreas Färber if (err) { 64a62c8911SAndreas Färber return err; 65a62c8911SAndreas Färber } 66a62c8911SAndreas Färber } 67a62c8911SAndreas Färber 68a62c8911SAndreas Färber return 0; 69a62c8911SAndreas Färber } 70a62c8911SAndreas Färber 71a62c8911SAndreas Färber static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) 72a62c8911SAndreas Färber { 73a62c8911SAndreas Färber const char *typename = object_get_typename(OBJECT(bus)); 74a62c8911SAndreas Färber BusClass *bc; 75f73480c3SMarc-André Lureau int i, bus_id; 76a62c8911SAndreas Färber 77a62c8911SAndreas Färber bus->parent = parent; 78a62c8911SAndreas Färber 79a62c8911SAndreas Färber if (name) { 80a62c8911SAndreas Färber bus->name = g_strdup(name); 81a62c8911SAndreas Färber } else if (bus->parent && bus->parent->id) { 82a62c8911SAndreas Färber /* parent device has id -> use it plus parent-bus-id for bus name */ 83a62c8911SAndreas Färber bus_id = bus->parent->num_child_bus; 84f73480c3SMarc-André Lureau bus->name = g_strdup_printf("%s.%d", bus->parent->id, bus_id); 85a62c8911SAndreas Färber } else { 86a62c8911SAndreas Färber /* no id -> use lowercase bus type plus global bus-id for bus name */ 87a62c8911SAndreas Färber bc = BUS_GET_CLASS(bus); 88a62c8911SAndreas Färber bus_id = bc->automatic_ids++; 89f73480c3SMarc-André Lureau bus->name = g_strdup_printf("%s.%d", typename, bus_id); 90f73480c3SMarc-André Lureau for (i = 0; bus->name[i]; i++) { 91f73480c3SMarc-André Lureau bus->name[i] = qemu_tolower(bus->name[i]); 92a62c8911SAndreas Färber } 93a62c8911SAndreas Färber } 94a62c8911SAndreas Färber 95a62c8911SAndreas Färber if (bus->parent) { 96a62c8911SAndreas Färber QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling); 97a62c8911SAndreas Färber bus->parent->num_child_bus++; 98a62c8911SAndreas Färber object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL); 990d1e8d6fSMarc-André Lureau object_unref(OBJECT(bus)); 100a62c8911SAndreas Färber } else if (bus != sysbus_get_default()) { 101a62c8911SAndreas Färber /* TODO: once all bus devices are qdevified, 102a62c8911SAndreas Färber only reset handler for main_system_bus should be registered here. */ 103a62c8911SAndreas Färber qemu_register_reset(qbus_reset_all_fn, bus); 104a62c8911SAndreas Färber } 105a62c8911SAndreas Färber } 106a62c8911SAndreas Färber 107a62c8911SAndreas Färber static void bus_unparent(Object *obj) 108a62c8911SAndreas Färber { 109a62c8911SAndreas Färber BusState *bus = BUS(obj); 110a62c8911SAndreas Färber BusChild *kid; 111a62c8911SAndreas Färber 112a62c8911SAndreas Färber while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { 113a62c8911SAndreas Färber DeviceState *dev = kid->child; 114a62c8911SAndreas Färber object_unparent(OBJECT(dev)); 115a62c8911SAndreas Färber } 116a62c8911SAndreas Färber if (bus->parent) { 117a62c8911SAndreas Färber QLIST_REMOVE(bus, sibling); 118a62c8911SAndreas Färber bus->parent->num_child_bus--; 119a62c8911SAndreas Färber bus->parent = NULL; 120a62c8911SAndreas Färber } else { 121a62c8911SAndreas Färber assert(bus != sysbus_get_default()); /* main_system_bus is never freed */ 122a62c8911SAndreas Färber qemu_unregister_reset(qbus_reset_all_fn, bus); 123a62c8911SAndreas Färber } 124a62c8911SAndreas Färber } 125a62c8911SAndreas Färber 126a62c8911SAndreas Färber void qbus_create_inplace(void *bus, size_t size, const char *typename, 127a62c8911SAndreas Färber DeviceState *parent, const char *name) 128a62c8911SAndreas Färber { 129a62c8911SAndreas Färber object_initialize(bus, size, typename); 130a62c8911SAndreas Färber qbus_realize(bus, parent, name); 131a62c8911SAndreas Färber } 132a62c8911SAndreas Färber 133a62c8911SAndreas Färber BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) 134a62c8911SAndreas Färber { 135a62c8911SAndreas Färber BusState *bus; 136a62c8911SAndreas Färber 137a62c8911SAndreas Färber bus = BUS(object_new(typename)); 138a62c8911SAndreas Färber qbus_realize(bus, parent, name); 139a62c8911SAndreas Färber 140a62c8911SAndreas Färber return bus; 141a62c8911SAndreas Färber } 142a62c8911SAndreas Färber 143a62c8911SAndreas Färber static bool bus_get_realized(Object *obj, Error **errp) 144a62c8911SAndreas Färber { 145a62c8911SAndreas Färber BusState *bus = BUS(obj); 146a62c8911SAndreas Färber 147a62c8911SAndreas Färber return bus->realized; 148a62c8911SAndreas Färber } 149a62c8911SAndreas Färber 150a62c8911SAndreas Färber static void bus_set_realized(Object *obj, bool value, Error **errp) 151a62c8911SAndreas Färber { 152a62c8911SAndreas Färber BusState *bus = BUS(obj); 153a62c8911SAndreas Färber BusClass *bc = BUS_GET_CLASS(bus); 154a62c8911SAndreas Färber BusChild *kid; 155a62c8911SAndreas Färber Error *local_err = NULL; 156a62c8911SAndreas Färber 157a62c8911SAndreas Färber if (value && !bus->realized) { 158a62c8911SAndreas Färber if (bc->realize) { 159a62c8911SAndreas Färber bc->realize(bus, &local_err); 160a62c8911SAndreas Färber } 161a62c8911SAndreas Färber 162a62c8911SAndreas Färber /* TODO: recursive realization */ 163a62c8911SAndreas Färber } else if (!value && bus->realized) { 164a62c8911SAndreas Färber QTAILQ_FOREACH(kid, &bus->children, sibling) { 165a62c8911SAndreas Färber DeviceState *dev = kid->child; 166a62c8911SAndreas Färber object_property_set_bool(OBJECT(dev), false, "realized", 167a62c8911SAndreas Färber &local_err); 168a62c8911SAndreas Färber if (local_err != NULL) { 169a62c8911SAndreas Färber break; 170a62c8911SAndreas Färber } 171a62c8911SAndreas Färber } 172a62c8911SAndreas Färber if (bc->unrealize && local_err == NULL) { 173a62c8911SAndreas Färber bc->unrealize(bus, &local_err); 174a62c8911SAndreas Färber } 175a62c8911SAndreas Färber } 176a62c8911SAndreas Färber 177a62c8911SAndreas Färber if (local_err != NULL) { 178a62c8911SAndreas Färber error_propagate(errp, local_err); 179a62c8911SAndreas Färber return; 180a62c8911SAndreas Färber } 181a62c8911SAndreas Färber 182a62c8911SAndreas Färber bus->realized = value; 183a62c8911SAndreas Färber } 184a62c8911SAndreas Färber 185a62c8911SAndreas Färber static void qbus_initfn(Object *obj) 186a62c8911SAndreas Färber { 187a62c8911SAndreas Färber BusState *bus = BUS(obj); 188a62c8911SAndreas Färber 189a62c8911SAndreas Färber QTAILQ_INIT(&bus->children); 190a62c8911SAndreas Färber object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, 191a62c8911SAndreas Färber TYPE_HOTPLUG_HANDLER, 192a62c8911SAndreas Färber (Object **)&bus->hotplug_handler, 193a62c8911SAndreas Färber object_property_allow_set_link, 194675f22c6SMarc-André Lureau 0, 195a62c8911SAndreas Färber NULL); 196a62c8911SAndreas Färber object_property_add_bool(obj, "realized", 197a62c8911SAndreas Färber bus_get_realized, bus_set_realized, NULL); 198a62c8911SAndreas Färber } 199a62c8911SAndreas Färber 200a62c8911SAndreas Färber static char *default_bus_get_fw_dev_path(DeviceState *dev) 201a62c8911SAndreas Färber { 202a62c8911SAndreas Färber return g_strdup(object_get_typename(OBJECT(dev))); 203a62c8911SAndreas Färber } 204a62c8911SAndreas Färber 205a62c8911SAndreas Färber static void bus_class_init(ObjectClass *class, void *data) 206a62c8911SAndreas Färber { 207a62c8911SAndreas Färber BusClass *bc = BUS_CLASS(class); 208a62c8911SAndreas Färber 209a62c8911SAndreas Färber class->unparent = bus_unparent; 210a62c8911SAndreas Färber bc->get_fw_dev_path = default_bus_get_fw_dev_path; 211a62c8911SAndreas Färber } 212a62c8911SAndreas Färber 213a62c8911SAndreas Färber static void qbus_finalize(Object *obj) 214a62c8911SAndreas Färber { 215a62c8911SAndreas Färber BusState *bus = BUS(obj); 216a62c8911SAndreas Färber 217f73480c3SMarc-André Lureau g_free(bus->name); 218a62c8911SAndreas Färber } 219a62c8911SAndreas Färber 220a62c8911SAndreas Färber static const TypeInfo bus_info = { 221a62c8911SAndreas Färber .name = TYPE_BUS, 222a62c8911SAndreas Färber .parent = TYPE_OBJECT, 223a62c8911SAndreas Färber .instance_size = sizeof(BusState), 224a62c8911SAndreas Färber .abstract = true, 225a62c8911SAndreas Färber .class_size = sizeof(BusClass), 226a62c8911SAndreas Färber .instance_init = qbus_initfn, 227a62c8911SAndreas Färber .instance_finalize = qbus_finalize, 228a62c8911SAndreas Färber .class_init = bus_class_init, 229a62c8911SAndreas Färber }; 230a62c8911SAndreas Färber 231a62c8911SAndreas Färber static void bus_register_types(void) 232a62c8911SAndreas Färber { 233a62c8911SAndreas Färber type_register_static(&bus_info); 234a62c8911SAndreas Färber } 235a62c8911SAndreas Färber 236a62c8911SAndreas Färber type_init(bus_register_types) 237