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" 21*856dfd8aSMarkus Armbruster #include "qemu/ctype.h" 22a62c8911SAndreas Färber #include "hw/qdev.h" 23a62c8911SAndreas Färber #include "qapi/error.h" 24a62c8911SAndreas Färber 2594d1cc5fSMichael Roth void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp) 26a62c8911SAndreas Färber { 27a62c8911SAndreas Färber object_property_set_link(OBJECT(bus), OBJECT(handler), 28a62c8911SAndreas Färber QDEV_HOTPLUG_HANDLER_PROPERTY, errp); 29a62c8911SAndreas Färber } 30a62c8911SAndreas Färber 31a62c8911SAndreas Färber void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp) 32a62c8911SAndreas Färber { 3394d1cc5fSMichael Roth qbus_set_hotplug_handler(bus, OBJECT(bus), errp); 34a62c8911SAndreas Färber } 35a62c8911SAndreas Färber 36a62c8911SAndreas Färber int qbus_walk_children(BusState *bus, 37a62c8911SAndreas Färber qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn, 38a62c8911SAndreas Färber qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn, 39a62c8911SAndreas Färber void *opaque) 40a62c8911SAndreas Färber { 41a62c8911SAndreas Färber BusChild *kid; 42a62c8911SAndreas Färber int err; 43a62c8911SAndreas Färber 44a62c8911SAndreas Färber if (pre_busfn) { 45a62c8911SAndreas Färber err = pre_busfn(bus, opaque); 46a62c8911SAndreas Färber if (err) { 47a62c8911SAndreas Färber return err; 48a62c8911SAndreas Färber } 49a62c8911SAndreas Färber } 50a62c8911SAndreas Färber 51a62c8911SAndreas Färber QTAILQ_FOREACH(kid, &bus->children, sibling) { 52a62c8911SAndreas Färber err = qdev_walk_children(kid->child, 53a62c8911SAndreas Färber pre_devfn, pre_busfn, 54a62c8911SAndreas Färber post_devfn, post_busfn, opaque); 55a62c8911SAndreas Färber if (err < 0) { 56a62c8911SAndreas Färber return err; 57a62c8911SAndreas Färber } 58a62c8911SAndreas Färber } 59a62c8911SAndreas Färber 60a62c8911SAndreas Färber if (post_busfn) { 61a62c8911SAndreas Färber err = post_busfn(bus, opaque); 62a62c8911SAndreas Färber if (err) { 63a62c8911SAndreas Färber return err; 64a62c8911SAndreas Färber } 65a62c8911SAndreas Färber } 66a62c8911SAndreas Färber 67a62c8911SAndreas Färber return 0; 68a62c8911SAndreas Färber } 69a62c8911SAndreas Färber 70a62c8911SAndreas Färber static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) 71a62c8911SAndreas Färber { 72a62c8911SAndreas Färber const char *typename = object_get_typename(OBJECT(bus)); 73a62c8911SAndreas Färber BusClass *bc; 74f73480c3SMarc-André Lureau int i, bus_id; 75a62c8911SAndreas Färber 76a62c8911SAndreas Färber bus->parent = parent; 77a62c8911SAndreas Färber 78a62c8911SAndreas Färber if (name) { 79a62c8911SAndreas Färber bus->name = g_strdup(name); 80a62c8911SAndreas Färber } else if (bus->parent && bus->parent->id) { 81a62c8911SAndreas Färber /* parent device has id -> use it plus parent-bus-id for bus name */ 82a62c8911SAndreas Färber bus_id = bus->parent->num_child_bus; 83f73480c3SMarc-André Lureau bus->name = g_strdup_printf("%s.%d", bus->parent->id, bus_id); 84a62c8911SAndreas Färber } else { 85a62c8911SAndreas Färber /* no id -> use lowercase bus type plus global bus-id for bus name */ 86a62c8911SAndreas Färber bc = BUS_GET_CLASS(bus); 87a62c8911SAndreas Färber bus_id = bc->automatic_ids++; 88f73480c3SMarc-André Lureau bus->name = g_strdup_printf("%s.%d", typename, bus_id); 89f73480c3SMarc-André Lureau for (i = 0; bus->name[i]; i++) { 90f73480c3SMarc-André Lureau bus->name[i] = qemu_tolower(bus->name[i]); 91a62c8911SAndreas Färber } 92a62c8911SAndreas Färber } 93a62c8911SAndreas Färber 94a62c8911SAndreas Färber if (bus->parent) { 95a62c8911SAndreas Färber QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling); 96a62c8911SAndreas Färber bus->parent->num_child_bus++; 97a62c8911SAndreas Färber object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL); 980d1e8d6fSMarc-André Lureau object_unref(OBJECT(bus)); 99a62c8911SAndreas Färber } else if (bus != sysbus_get_default()) { 100a62c8911SAndreas Färber /* TODO: once all bus devices are qdevified, 101a62c8911SAndreas Färber only reset handler for main_system_bus should be registered here. */ 102a62c8911SAndreas Färber qemu_register_reset(qbus_reset_all_fn, bus); 103a62c8911SAndreas Färber } 104a62c8911SAndreas Färber } 105a62c8911SAndreas Färber 106a62c8911SAndreas Färber static void bus_unparent(Object *obj) 107a62c8911SAndreas Färber { 108a62c8911SAndreas Färber BusState *bus = BUS(obj); 109a62c8911SAndreas Färber BusChild *kid; 110a62c8911SAndreas Färber 111a62c8911SAndreas Färber while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { 112a62c8911SAndreas Färber DeviceState *dev = kid->child; 113a62c8911SAndreas Färber object_unparent(OBJECT(dev)); 114a62c8911SAndreas Färber } 115a62c8911SAndreas Färber if (bus->parent) { 116a62c8911SAndreas Färber QLIST_REMOVE(bus, sibling); 117a62c8911SAndreas Färber bus->parent->num_child_bus--; 118a62c8911SAndreas Färber bus->parent = NULL; 119a62c8911SAndreas Färber } else { 120a62c8911SAndreas Färber assert(bus != sysbus_get_default()); /* main_system_bus is never freed */ 121a62c8911SAndreas Färber qemu_unregister_reset(qbus_reset_all_fn, bus); 122a62c8911SAndreas Färber } 123a62c8911SAndreas Färber } 124a62c8911SAndreas Färber 125a62c8911SAndreas Färber void qbus_create_inplace(void *bus, size_t size, const char *typename, 126a62c8911SAndreas Färber DeviceState *parent, const char *name) 127a62c8911SAndreas Färber { 128a62c8911SAndreas Färber object_initialize(bus, size, typename); 129a62c8911SAndreas Färber qbus_realize(bus, parent, name); 130a62c8911SAndreas Färber } 131a62c8911SAndreas Färber 132a62c8911SAndreas Färber BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) 133a62c8911SAndreas Färber { 134a62c8911SAndreas Färber BusState *bus; 135a62c8911SAndreas Färber 136a62c8911SAndreas Färber bus = BUS(object_new(typename)); 137a62c8911SAndreas Färber qbus_realize(bus, parent, name); 138a62c8911SAndreas Färber 139a62c8911SAndreas Färber return bus; 140a62c8911SAndreas Färber } 141a62c8911SAndreas Färber 142a62c8911SAndreas Färber static bool bus_get_realized(Object *obj, Error **errp) 143a62c8911SAndreas Färber { 144a62c8911SAndreas Färber BusState *bus = BUS(obj); 145a62c8911SAndreas Färber 146a62c8911SAndreas Färber return bus->realized; 147a62c8911SAndreas Färber } 148a62c8911SAndreas Färber 149a62c8911SAndreas Färber static void bus_set_realized(Object *obj, bool value, Error **errp) 150a62c8911SAndreas Färber { 151a62c8911SAndreas Färber BusState *bus = BUS(obj); 152a62c8911SAndreas Färber BusClass *bc = BUS_GET_CLASS(bus); 153a62c8911SAndreas Färber BusChild *kid; 154a62c8911SAndreas Färber Error *local_err = NULL; 155a62c8911SAndreas Färber 156a62c8911SAndreas Färber if (value && !bus->realized) { 157a62c8911SAndreas Färber if (bc->realize) { 158a62c8911SAndreas Färber bc->realize(bus, &local_err); 159a62c8911SAndreas Färber } 160a62c8911SAndreas Färber 161a62c8911SAndreas Färber /* TODO: recursive realization */ 162a62c8911SAndreas Färber } else if (!value && bus->realized) { 163a62c8911SAndreas Färber QTAILQ_FOREACH(kid, &bus->children, sibling) { 164a62c8911SAndreas Färber DeviceState *dev = kid->child; 165a62c8911SAndreas Färber object_property_set_bool(OBJECT(dev), false, "realized", 166a62c8911SAndreas Färber &local_err); 167a62c8911SAndreas Färber if (local_err != NULL) { 168a62c8911SAndreas Färber break; 169a62c8911SAndreas Färber } 170a62c8911SAndreas Färber } 171a62c8911SAndreas Färber if (bc->unrealize && local_err == NULL) { 172a62c8911SAndreas Färber bc->unrealize(bus, &local_err); 173a62c8911SAndreas Färber } 174a62c8911SAndreas Färber } 175a62c8911SAndreas Färber 176a62c8911SAndreas Färber if (local_err != NULL) { 177a62c8911SAndreas Färber error_propagate(errp, local_err); 178a62c8911SAndreas Färber return; 179a62c8911SAndreas Färber } 180a62c8911SAndreas Färber 181a62c8911SAndreas Färber bus->realized = value; 182a62c8911SAndreas Färber } 183a62c8911SAndreas Färber 184a62c8911SAndreas Färber static void qbus_initfn(Object *obj) 185a62c8911SAndreas Färber { 186a62c8911SAndreas Färber BusState *bus = BUS(obj); 187a62c8911SAndreas Färber 188a62c8911SAndreas Färber QTAILQ_INIT(&bus->children); 189a62c8911SAndreas Färber object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, 190a62c8911SAndreas Färber TYPE_HOTPLUG_HANDLER, 191a62c8911SAndreas Färber (Object **)&bus->hotplug_handler, 192a62c8911SAndreas Färber object_property_allow_set_link, 193675f22c6SMarc-André Lureau 0, 194a62c8911SAndreas Färber NULL); 195a62c8911SAndreas Färber object_property_add_bool(obj, "realized", 196a62c8911SAndreas Färber bus_get_realized, bus_set_realized, NULL); 197a62c8911SAndreas Färber } 198a62c8911SAndreas Färber 199a62c8911SAndreas Färber static char *default_bus_get_fw_dev_path(DeviceState *dev) 200a62c8911SAndreas Färber { 201a62c8911SAndreas Färber return g_strdup(object_get_typename(OBJECT(dev))); 202a62c8911SAndreas Färber } 203a62c8911SAndreas Färber 204a62c8911SAndreas Färber static void bus_class_init(ObjectClass *class, void *data) 205a62c8911SAndreas Färber { 206a62c8911SAndreas Färber BusClass *bc = BUS_CLASS(class); 207a62c8911SAndreas Färber 208a62c8911SAndreas Färber class->unparent = bus_unparent; 209a62c8911SAndreas Färber bc->get_fw_dev_path = default_bus_get_fw_dev_path; 210a62c8911SAndreas Färber } 211a62c8911SAndreas Färber 212a62c8911SAndreas Färber static void qbus_finalize(Object *obj) 213a62c8911SAndreas Färber { 214a62c8911SAndreas Färber BusState *bus = BUS(obj); 215a62c8911SAndreas Färber 216f73480c3SMarc-André Lureau g_free(bus->name); 217a62c8911SAndreas Färber } 218a62c8911SAndreas Färber 219a62c8911SAndreas Färber static const TypeInfo bus_info = { 220a62c8911SAndreas Färber .name = TYPE_BUS, 221a62c8911SAndreas Färber .parent = TYPE_OBJECT, 222a62c8911SAndreas Färber .instance_size = sizeof(BusState), 223a62c8911SAndreas Färber .abstract = true, 224a62c8911SAndreas Färber .class_size = sizeof(BusClass), 225a62c8911SAndreas Färber .instance_init = qbus_initfn, 226a62c8911SAndreas Färber .instance_finalize = qbus_finalize, 227a62c8911SAndreas Färber .class_init = bus_class_init, 228a62c8911SAndreas Färber }; 229a62c8911SAndreas Färber 230a62c8911SAndreas Färber static void bus_register_types(void) 231a62c8911SAndreas Färber { 232a62c8911SAndreas Färber type_register_static(&bus_info); 233a62c8911SAndreas Färber } 234a62c8911SAndreas Färber 235a62c8911SAndreas Färber type_init(bus_register_types) 236