xref: /qemu/hw/core/bus.c (revision a62c89117fa19adc6f9242844468ac31ec535d7e)
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