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