]> Git Repo - qemu.git/blob - hw/qdev.c
qdev: remove duplication between qbus_create and qbus_create_inplace
[qemu.git] / hw / qdev.c
1 /*
2  *  Dynamic device configuration and creation.
3  *
4  *  Copyright (c) 2009 CodeSourcery
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* The theory here is that it should be possible to create a machine without
21    knowledge of specific devices.  Historically board init routines have
22    passed a bunch of arguments to each device, requiring the board know
23    exactly which device it is dealing with.  This file provides an abstract
24    API for device configuration and initialization.  Devices will generally
25    inherit from a particular bus (e.g. PCI or I2C) rather than
26    this API directly.  */
27
28 #include "qdev.h"
29 #include "sysemu/sysemu.h"
30 #include "qapi/error.h"
31 #include "qapi/visitor.h"
32
33 int qdev_hotplug = 0;
34 static bool qdev_hot_added = false;
35 static bool qdev_hot_removed = false;
36
37 const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
38 {
39     DeviceClass *dc = DEVICE_GET_CLASS(dev);
40     return dc->vmsd;
41 }
42
43 const char *qdev_fw_name(DeviceState *dev)
44 {
45     DeviceClass *dc = DEVICE_GET_CLASS(dev);
46
47     if (dc->fw_name) {
48         return dc->fw_name;
49     }
50
51     return object_get_typename(OBJECT(dev));
52 }
53
54 static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
55                                      Error **errp);
56
57 static void bus_remove_child(BusState *bus, DeviceState *child)
58 {
59     BusChild *kid;
60
61     QTAILQ_FOREACH(kid, &bus->children, sibling) {
62         if (kid->child == child) {
63             char name[32];
64
65             snprintf(name, sizeof(name), "child[%d]", kid->index);
66             QTAILQ_REMOVE(&bus->children, kid, sibling);
67             object_property_del(OBJECT(bus), name, NULL);
68             g_free(kid);
69             return;
70         }
71     }
72 }
73
74 static void bus_add_child(BusState *bus, DeviceState *child)
75 {
76     char name[32];
77     BusChild *kid = g_malloc0(sizeof(*kid));
78
79     if (qdev_hotplug) {
80         assert(bus->allow_hotplug);
81     }
82
83     kid->index = bus->max_index++;
84     kid->child = child;
85
86     QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
87
88     snprintf(name, sizeof(name), "child[%d]", kid->index);
89     object_property_add_link(OBJECT(bus), name,
90                              object_get_typename(OBJECT(child)),
91                              (Object **)&kid->child,
92                              NULL);
93 }
94
95 void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
96 {
97     dev->parent_bus = bus;
98     bus_add_child(bus, dev);
99 }
100
101 /* Create a new device.  This only initializes the device state structure
102    and allows properties to be set.  qdev_init should be called to
103    initialize the actual device emulation.  */
104 DeviceState *qdev_create(BusState *bus, const char *name)
105 {
106     DeviceState *dev;
107
108     dev = qdev_try_create(bus, name);
109     if (!dev) {
110         if (bus) {
111             error_report("Unknown device '%s' for bus '%s'\n", name,
112                          object_get_typename(OBJECT(bus)));
113             abort();
114         } else {
115             error_report("Unknown device '%s' for default sysbus\n", name);
116             abort();
117         }
118     }
119
120     return dev;
121 }
122
123 DeviceState *qdev_try_create(BusState *bus, const char *type)
124 {
125     DeviceState *dev;
126
127     if (object_class_by_name(type) == NULL) {
128         return NULL;
129     }
130     dev = DEVICE(object_new(type));
131     if (!dev) {
132         return NULL;
133     }
134
135     if (!bus) {
136         bus = sysbus_get_default();
137     }
138
139     qdev_set_parent_bus(dev, bus);
140
141     return dev;
142 }
143
144 /* Initialize a device.  Device properties should be set before calling
145    this function.  IRQs and MMIO regions should be connected/mapped after
146    calling this function.
147    On failure, destroy the device and return negative value.
148    Return 0 on success.  */
149 int qdev_init(DeviceState *dev)
150 {
151     Error *local_err = NULL;
152
153     assert(!dev->realized);
154
155     object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
156     if (local_err != NULL) {
157         error_free(local_err);
158         qdev_free(dev);
159         return -1;
160     }
161     return 0;
162 }
163
164 static void device_realize(DeviceState *dev, Error **err)
165 {
166     DeviceClass *dc = DEVICE_GET_CLASS(dev);
167
168     if (dc->init) {
169         int rc = dc->init(dev);
170         if (rc < 0) {
171             error_setg(err, "Device initialization failed.");
172             return;
173         }
174     }
175 }
176
177 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
178                                  int required_for_version)
179 {
180     assert(!dev->realized);
181     dev->instance_id_alias = alias_id;
182     dev->alias_required_for_version = required_for_version;
183 }
184
185 void qdev_unplug(DeviceState *dev, Error **errp)
186 {
187     DeviceClass *dc = DEVICE_GET_CLASS(dev);
188
189     if (!dev->parent_bus->allow_hotplug) {
190         error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
191         return;
192     }
193     assert(dc->unplug != NULL);
194
195     qdev_hot_removed = true;
196
197     if (dc->unplug(dev) < 0) {
198         error_set(errp, QERR_UNDEFINED_ERROR);
199         return;
200     }
201 }
202
203 static int qdev_reset_one(DeviceState *dev, void *opaque)
204 {
205     device_reset(dev);
206
207     return 0;
208 }
209
210 static int qbus_reset_one(BusState *bus, void *opaque)
211 {
212     BusClass *bc = BUS_GET_CLASS(bus);
213     if (bc->reset) {
214         return bc->reset(bus);
215     }
216     return 0;
217 }
218
219 void qdev_reset_all(DeviceState *dev)
220 {
221     qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
222 }
223
224 void qbus_reset_all(BusState *bus)
225 {
226     qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
227 }
228
229 void qbus_reset_all_fn(void *opaque)
230 {
231     BusState *bus = opaque;
232     qbus_reset_all(bus);
233 }
234
235 /* can be used as ->unplug() callback for the simple cases */
236 int qdev_simple_unplug_cb(DeviceState *dev)
237 {
238     /* just zap it */
239     qdev_free(dev);
240     return 0;
241 }
242
243
244 /* Like qdev_init(), but terminate program via error_report() instead of
245    returning an error value.  This is okay during machine creation.
246    Don't use for hotplug, because there callers need to recover from
247    failure.  Exception: if you know the device's init() callback can't
248    fail, then qdev_init_nofail() can't fail either, and is therefore
249    usable even then.  But relying on the device implementation that
250    way is somewhat unclean, and best avoided.  */
251 void qdev_init_nofail(DeviceState *dev)
252 {
253     const char *typename = object_get_typename(OBJECT(dev));
254
255     if (qdev_init(dev) < 0) {
256         error_report("Initialization of device %s failed", typename);
257         exit(1);
258     }
259 }
260
261 /* Unlink device from bus and free the structure.  */
262 void qdev_free(DeviceState *dev)
263 {
264     object_delete(OBJECT(dev));
265 }
266
267 void qdev_machine_creation_done(void)
268 {
269     /*
270      * ok, initial machine setup is done, starting from now we can
271      * only create hotpluggable devices
272      */
273     qdev_hotplug = 1;
274 }
275
276 bool qdev_machine_modified(void)
277 {
278     return qdev_hot_added || qdev_hot_removed;
279 }
280
281 BusState *qdev_get_parent_bus(DeviceState *dev)
282 {
283     return dev->parent_bus;
284 }
285
286 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
287 {
288     dev->gpio_in = qemu_extend_irqs(dev->gpio_in, dev->num_gpio_in, handler,
289                                         dev, n);
290     dev->num_gpio_in += n;
291 }
292
293 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
294 {
295     assert(dev->num_gpio_out == 0);
296     dev->num_gpio_out = n;
297     dev->gpio_out = pins;
298 }
299
300 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
301 {
302     assert(n >= 0 && n < dev->num_gpio_in);
303     return dev->gpio_in[n];
304 }
305
306 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
307 {
308     assert(n >= 0 && n < dev->num_gpio_out);
309     dev->gpio_out[n] = pin;
310 }
311
312 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
313 {
314     BusState *bus;
315
316     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
317         if (strcmp(name, bus->name) == 0) {
318             return bus;
319         }
320     }
321     return NULL;
322 }
323
324 int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
325                        qbus_walkerfn *busfn, void *opaque)
326 {
327     BusChild *kid;
328     int err;
329
330     if (busfn) {
331         err = busfn(bus, opaque);
332         if (err) {
333             return err;
334         }
335     }
336
337     QTAILQ_FOREACH(kid, &bus->children, sibling) {
338         err = qdev_walk_children(kid->child, devfn, busfn, opaque);
339         if (err < 0) {
340             return err;
341         }
342     }
343
344     return 0;
345 }
346
347 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
348                        qbus_walkerfn *busfn, void *opaque)
349 {
350     BusState *bus;
351     int err;
352
353     if (devfn) {
354         err = devfn(dev, opaque);
355         if (err) {
356             return err;
357         }
358     }
359
360     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
361         err = qbus_walk_children(bus, devfn, busfn, opaque);
362         if (err < 0) {
363             return err;
364         }
365     }
366
367     return 0;
368 }
369
370 DeviceState *qdev_find_recursive(BusState *bus, const char *id)
371 {
372     BusChild *kid;
373     DeviceState *ret;
374     BusState *child;
375
376     QTAILQ_FOREACH(kid, &bus->children, sibling) {
377         DeviceState *dev = kid->child;
378
379         if (dev->id && strcmp(dev->id, id) == 0) {
380             return dev;
381         }
382
383         QLIST_FOREACH(child, &dev->child_bus, sibling) {
384             ret = qdev_find_recursive(child, id);
385             if (ret) {
386                 return ret;
387             }
388         }
389     }
390     return NULL;
391 }
392
393 static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
394 {
395     const char *typename = object_get_typename(OBJECT(bus));
396     char *buf;
397     int i,len;
398
399     bus->parent = parent;
400
401     if (name) {
402         bus->name = g_strdup(name);
403     } else if (bus->parent && bus->parent->id) {
404         /* parent device has id -> use it for bus name */
405         len = strlen(bus->parent->id) + 16;
406         buf = g_malloc(len);
407         snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus);
408         bus->name = buf;
409     } else {
410         /* no id -> use lowercase bus type for bus name */
411         len = strlen(typename) + 16;
412         buf = g_malloc(len);
413         len = snprintf(buf, len, "%s.%d", typename,
414                        bus->parent ? bus->parent->num_child_bus : 0);
415         for (i = 0; i < len; i++)
416             buf[i] = qemu_tolower(buf[i]);
417         bus->name = buf;
418     }
419
420     if (bus->parent) {
421         QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
422         bus->parent->num_child_bus++;
423         object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
424     } else if (bus != sysbus_get_default()) {
425         /* TODO: once all bus devices are qdevified,
426            only reset handler for main_system_bus should be registered here. */
427         qemu_register_reset(qbus_reset_all_fn, bus);
428     }
429 }
430
431 void qbus_create_inplace(BusState *bus, const char *typename,
432                          DeviceState *parent, const char *name)
433 {
434     object_initialize(bus, typename);
435     qbus_realize(bus, parent, name);
436 }
437
438 BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
439 {
440     BusState *bus;
441
442     bus = BUS(object_new(typename));
443     qbus_realize(bus, parent, name);
444
445     return bus;
446 }
447
448 void qbus_free(BusState *bus)
449 {
450     object_delete(OBJECT(bus));
451 }
452
453 static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev)
454 {
455     BusClass *bc = BUS_GET_CLASS(bus);
456
457     if (bc->get_fw_dev_path) {
458         return bc->get_fw_dev_path(dev);
459     }
460
461     return NULL;
462 }
463
464 static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
465 {
466     int l = 0;
467
468     if (dev && dev->parent_bus) {
469         char *d;
470         l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
471         d = bus_get_fw_dev_path(dev->parent_bus, dev);
472         if (d) {
473             l += snprintf(p + l, size - l, "%s", d);
474             g_free(d);
475         } else {
476             l += snprintf(p + l, size - l, "%s", object_get_typename(OBJECT(dev)));
477         }
478     }
479     l += snprintf(p + l , size - l, "/");
480
481     return l;
482 }
483
484 char* qdev_get_fw_dev_path(DeviceState *dev)
485 {
486     char path[128];
487     int l;
488
489     l = qdev_get_fw_dev_path_helper(dev, path, 128);
490
491     path[l-1] = '\0';
492
493     return g_strdup(path);
494 }
495
496 char *qdev_get_dev_path(DeviceState *dev)
497 {
498     BusClass *bc;
499
500     if (!dev || !dev->parent_bus) {
501         return NULL;
502     }
503
504     bc = BUS_GET_CLASS(dev->parent_bus);
505     if (bc->get_dev_path) {
506         return bc->get_dev_path(dev);
507     }
508
509     return NULL;
510 }
511
512 /**
513  * Legacy property handling
514  */
515
516 static void qdev_get_legacy_property(Object *obj, Visitor *v, void *opaque,
517                                      const char *name, Error **errp)
518 {
519     DeviceState *dev = DEVICE(obj);
520     Property *prop = opaque;
521
522     char buffer[1024];
523     char *ptr = buffer;
524
525     prop->info->print(dev, prop, buffer, sizeof(buffer));
526     visit_type_str(v, &ptr, name, errp);
527 }
528
529 static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
530                                      const char *name, Error **errp)
531 {
532     DeviceState *dev = DEVICE(obj);
533     Property *prop = opaque;
534     Error *local_err = NULL;
535     char *ptr = NULL;
536     int ret;
537
538     if (dev->realized) {
539         error_set(errp, QERR_PERMISSION_DENIED);
540         return;
541     }
542
543     visit_type_str(v, &ptr, name, &local_err);
544     if (local_err) {
545         error_propagate(errp, local_err);
546         return;
547     }
548
549     ret = prop->info->parse(dev, prop, ptr);
550     error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
551     g_free(ptr);
552 }
553
554 /**
555  * @qdev_add_legacy_property - adds a legacy property
556  *
557  * Do not use this is new code!  Properties added through this interface will
558  * be given names and types in the "legacy" namespace.
559  *
560  * Legacy properties are string versions of other OOM properties.  The format
561  * of the string depends on the property type.
562  */
563 void qdev_property_add_legacy(DeviceState *dev, Property *prop,
564                               Error **errp)
565 {
566     gchar *name, *type;
567
568     /* Register pointer properties as legacy properties */
569     if (!prop->info->print && !prop->info->parse &&
570         (prop->info->set || prop->info->get)) {
571         return;
572     }
573
574     name = g_strdup_printf("legacy-%s", prop->name);
575     type = g_strdup_printf("legacy<%s>",
576                            prop->info->legacy_name ?: prop->info->name);
577
578     object_property_add(OBJECT(dev), name, type,
579                         prop->info->print ? qdev_get_legacy_property : prop->info->get,
580                         prop->info->parse ? qdev_set_legacy_property : prop->info->set,
581                         NULL,
582                         prop, errp);
583
584     g_free(type);
585     g_free(name);
586 }
587
588 /**
589  * @qdev_property_add_static - add a @Property to a device.
590  *
591  * Static properties access data in a struct.  The actual type of the
592  * property and the field depends on the property type.
593  */
594 void qdev_property_add_static(DeviceState *dev, Property *prop,
595                               Error **errp)
596 {
597     Error *local_err = NULL;
598     Object *obj = OBJECT(dev);
599
600     /*
601      * TODO qdev_prop_ptr does not have getters or setters.  It must
602      * go now that it can be replaced with links.  The test should be
603      * removed along with it: all static properties are read/write.
604      */
605     if (!prop->info->get && !prop->info->set) {
606         return;
607     }
608
609     object_property_add(obj, prop->name, prop->info->name,
610                         prop->info->get, prop->info->set,
611                         prop->info->release,
612                         prop, &local_err);
613
614     if (local_err) {
615         error_propagate(errp, local_err);
616         return;
617     }
618     if (prop->qtype == QTYPE_NONE) {
619         return;
620     }
621
622     if (prop->qtype == QTYPE_QBOOL) {
623         object_property_set_bool(obj, prop->defval, prop->name, &local_err);
624     } else if (prop->info->enum_table) {
625         object_property_set_str(obj, prop->info->enum_table[prop->defval],
626                                 prop->name, &local_err);
627     } else if (prop->qtype == QTYPE_QINT) {
628         object_property_set_int(obj, prop->defval, prop->name, &local_err);
629     }
630     assert_no_error(local_err);
631 }
632
633 static bool device_get_realized(Object *obj, Error **err)
634 {
635     DeviceState *dev = DEVICE(obj);
636     return dev->realized;
637 }
638
639 static void device_set_realized(Object *obj, bool value, Error **err)
640 {
641     DeviceState *dev = DEVICE(obj);
642     DeviceClass *dc = DEVICE_GET_CLASS(dev);
643     Error *local_err = NULL;
644
645     if (value && !dev->realized) {
646         if (dc->realize) {
647             dc->realize(dev, &local_err);
648         }
649
650         if (!obj->parent && local_err == NULL) {
651             static int unattached_count;
652             gchar *name = g_strdup_printf("device[%d]", unattached_count++);
653
654             object_property_add_child(container_get(qdev_get_machine(),
655                                                     "/unattached"),
656                                       name, obj, &local_err);
657             g_free(name);
658         }
659
660         if (qdev_get_vmsd(dev) && local_err == NULL) {
661             vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
662                                            dev->instance_id_alias,
663                                            dev->alias_required_for_version);
664         }
665         if (dev->hotplugged && local_err == NULL) {
666             device_reset(dev);
667         }
668     } else if (!value && dev->realized) {
669         if (dc->unrealize) {
670             dc->unrealize(dev, &local_err);
671         }
672     }
673
674     if (local_err != NULL) {
675         error_propagate(err, local_err);
676         return;
677     }
678
679     dev->realized = value;
680 }
681
682 static void device_initfn(Object *obj)
683 {
684     DeviceState *dev = DEVICE(obj);
685     ObjectClass *class;
686     Property *prop;
687
688     if (qdev_hotplug) {
689         dev->hotplugged = 1;
690         qdev_hot_added = true;
691     }
692
693     dev->instance_id_alias = -1;
694     dev->realized = false;
695
696     object_property_add_bool(obj, "realized",
697                              device_get_realized, device_set_realized, NULL);
698
699     class = object_get_class(OBJECT(dev));
700     do {
701         for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
702             qdev_property_add_legacy(dev, prop, NULL);
703             qdev_property_add_static(dev, prop, NULL);
704         }
705         class = object_class_get_parent(class);
706     } while (class != object_class_by_name(TYPE_DEVICE));
707     qdev_prop_set_globals(dev);
708
709     object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
710                              (Object **)&dev->parent_bus, NULL);
711 }
712
713 /* Unlink device from bus and free the structure.  */
714 static void device_finalize(Object *obj)
715 {
716     DeviceState *dev = DEVICE(obj);
717     BusState *bus;
718     DeviceClass *dc = DEVICE_GET_CLASS(dev);
719
720     if (dev->realized) {
721         while (dev->num_child_bus) {
722             bus = QLIST_FIRST(&dev->child_bus);
723             qbus_free(bus);
724         }
725         if (qdev_get_vmsd(dev)) {
726             vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
727         }
728         if (dc->exit) {
729             dc->exit(dev);
730         }
731         if (dev->opts) {
732             qemu_opts_del(dev->opts);
733         }
734     }
735 }
736
737 static void device_class_base_init(ObjectClass *class, void *data)
738 {
739     DeviceClass *klass = DEVICE_CLASS(class);
740
741     /* We explicitly look up properties in the superclasses,
742      * so do not propagate them to the subclasses.
743      */
744     klass->props = NULL;
745 }
746
747 static void device_unparent(Object *obj)
748 {
749     DeviceState *dev = DEVICE(obj);
750
751     if (dev->parent_bus != NULL) {
752         bus_remove_child(dev->parent_bus, dev);
753     }
754 }
755
756 static void device_class_init(ObjectClass *class, void *data)
757 {
758     DeviceClass *dc = DEVICE_CLASS(class);
759
760     class->unparent = device_unparent;
761     dc->realize = device_realize;
762 }
763
764 void device_reset(DeviceState *dev)
765 {
766     DeviceClass *klass = DEVICE_GET_CLASS(dev);
767
768     if (klass->reset) {
769         klass->reset(dev);
770     }
771 }
772
773 Object *qdev_get_machine(void)
774 {
775     static Object *dev;
776
777     if (dev == NULL) {
778         dev = container_get(object_get_root(), "/machine");
779     }
780
781     return dev;
782 }
783
784 static const TypeInfo device_type_info = {
785     .name = TYPE_DEVICE,
786     .parent = TYPE_OBJECT,
787     .instance_size = sizeof(DeviceState),
788     .instance_init = device_initfn,
789     .instance_finalize = device_finalize,
790     .class_base_init = device_class_base_init,
791     .class_init = device_class_init,
792     .abstract = true,
793     .class_size = sizeof(DeviceClass),
794 };
795
796 static void qbus_initfn(Object *obj)
797 {
798     BusState *bus = BUS(obj);
799
800     QTAILQ_INIT(&bus->children);
801 }
802
803 static void qbus_finalize(Object *obj)
804 {
805     BusState *bus = BUS(obj);
806     BusChild *kid;
807
808     while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
809         DeviceState *dev = kid->child;
810         qdev_free(dev);
811     }
812     if (bus->parent) {
813         QLIST_REMOVE(bus, sibling);
814         bus->parent->num_child_bus--;
815     } else {
816         assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
817         qemu_unregister_reset(qbus_reset_all_fn, bus);
818     }
819     g_free((char *)bus->name);
820 }
821
822 static const TypeInfo bus_info = {
823     .name = TYPE_BUS,
824     .parent = TYPE_OBJECT,
825     .instance_size = sizeof(BusState),
826     .abstract = true,
827     .class_size = sizeof(BusClass),
828     .instance_init = qbus_initfn,
829     .instance_finalize = qbus_finalize,
830 };
831
832 static void qdev_register_types(void)
833 {
834     type_register_static(&bus_info);
835     type_register_static(&device_type_info);
836 }
837
838 type_init(qdev_register_types)
This page took 0.067527 seconds and 4 git commands to generate.