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