| #ifndef QDEV_CORE_H |
| #define QDEV_CORE_H |
| |
| #include "qemu/queue.h" |
| #include "qemu/option.h" |
| #include "qemu/typedefs.h" |
| #include "qemu/bitmap.h" |
| #include "qom/object.h" |
| #include "hw/irq.h" |
| #include "qapi/error.h" |
| #include "hw/hotplug.h" |
| |
| enum { |
| DEV_NVECTORS_UNSPECIFIED = -1, |
| }; |
| |
| #define TYPE_DEVICE "device" |
| #define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) |
| #define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE) |
| #define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE) |
| |
| typedef enum DeviceCategory { |
| DEVICE_CATEGORY_BRIDGE, |
| DEVICE_CATEGORY_USB, |
| DEVICE_CATEGORY_STORAGE, |
| DEVICE_CATEGORY_NETWORK, |
| DEVICE_CATEGORY_INPUT, |
| DEVICE_CATEGORY_DISPLAY, |
| DEVICE_CATEGORY_SOUND, |
| DEVICE_CATEGORY_MISC, |
| DEVICE_CATEGORY_MAX |
| } DeviceCategory; |
| |
| typedef int (*qdev_initfn)(DeviceState *dev); |
| typedef int (*qdev_event)(DeviceState *dev); |
| typedef void (*qdev_resetfn)(DeviceState *dev); |
| typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); |
| typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp); |
| typedef void (*BusRealize)(BusState *bus, Error **errp); |
| typedef void (*BusUnrealize)(BusState *bus, Error **errp); |
| |
| struct VMStateDescription; |
| |
| /** |
| * DeviceClass: |
| * @props: Properties accessing state fields. |
| * @realize: Callback function invoked when the #DeviceState:realized |
| * property is changed to %true. The default invokes @init if not %NULL. |
| * @unrealize: Callback function invoked when the #DeviceState:realized |
| * property is changed to %false. |
| * @init: Callback function invoked when the #DeviceState::realized property |
| * is changed to %true. Deprecated, new types inheriting directly from |
| * TYPE_DEVICE should use @realize instead, new leaf types should consult |
| * their respective parent type. |
| * @hotpluggable: indicates if #DeviceClass is hotpluggable, available |
| * as readonly "hotpluggable" property of #DeviceState instance |
| * |
| * # Realization # |
| * Devices are constructed in two stages, |
| * 1) object instantiation via object_initialize() and |
| * 2) device realization via #DeviceState:realized property. |
| * The former may not fail (it might assert or exit), the latter may return |
| * error information to the caller and must be re-entrant. |
| * Trivial field initializations should go into #TypeInfo.instance_init. |
| * Operations depending on @props static properties should go into @realize. |
| * After successful realization, setting static properties will fail. |
| * |
| * As an interim step, the #DeviceState:realized property is set by deprecated |
| * functions qdev_init() and qdev_init_nofail(). |
| * In the future, devices will propagate this state change to their children |
| * and along busses they expose. |
| * The point in time will be deferred to machine creation, so that values |
| * set in @realize will not be introspectable beforehand. Therefore devices |
| * must not create children during @realize; they should initialize them via |
| * object_initialize() in their own #TypeInfo.instance_init and forward the |
| * realization events appropriately. |
| * |
| * The @init callback is considered private to a particular bus implementation |
| * (immediate abstract child types of TYPE_DEVICE). Derived leaf types set an |
| * "init" callback on their parent class instead. |
| * |
| * Any type may override the @realize and/or @unrealize callbacks but needs |
| * to call the parent type's implementation if keeping their functionality |
| * is desired. Refer to QOM documentation for further discussion and examples. |
| * |
| * <note> |
| * <para> |
| * If a type derived directly from TYPE_DEVICE implements @realize, it does |
| * not need to implement @init and therefore does not need to store and call |
| * #DeviceClass' default @realize callback. |
| * For other types consult the documentation and implementation of the |
| * respective parent types. |
| * </para> |
| * </note> |
| */ |
| typedef struct DeviceClass { |
| /*< private >*/ |
| ObjectClass parent_class; |
| /*< public >*/ |
| |
| DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX); |
| const char *fw_name; |
| const char *desc; |
| Property *props; |
| |
| /* |
| * Shall we hide this device model from -device / device_add? |
| * All devices should support instantiation with device_add, and |
| * this flag should not exist. But we're not there, yet. Some |
| * devices fail to instantiate with cryptic error messages. |
| * Others instantiate, but don't work. Exposing users to such |
| * behavior would be cruel; this flag serves to protect them. It |
| * should never be set without a comment explaining why it is set. |
| * TODO remove once we're there |
| */ |
| bool cannot_instantiate_with_device_add_yet; |
| bool hotpluggable; |
| |
| /* callbacks */ |
| void (*reset)(DeviceState *dev); |
| DeviceRealize realize; |
| DeviceUnrealize unrealize; |
| |
| /* device state */ |
| const struct VMStateDescription *vmsd; |
| |
| /* Private to qdev / bus. */ |
| qdev_initfn init; /* TODO remove, once users are converted to realize */ |
| qdev_event unplug; |
| qdev_event exit; /* TODO remove, once users are converted to unrealize */ |
| const char *bus_type; |
| } DeviceClass; |
| |
| |
| typedef struct DeviceType DeviceType; |
| |
| typedef struct DeviceProperty DeviceProperty; |
| |
| /* This structure should not be accessed directly. We declare it here |
| so that it can be embedded in individual device state structures. */ |
| struct DeviceState { |
| DeviceType *type; |
| BusState *parent_bus; |
| DeviceProperty *props; |
| int num_gpio_out; |
| qemu_irq *gpio_out; |
| int num_gpio_in; |
| qemu_irq *gpio_in; |
| QLIST_HEAD(, BusState) child_bus; |
| QLIST_ENTRY(DeviceState) sibling; |
| }; |
| |
| #define TYPE_BUS "bus" |
| #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) |
| #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) |
| #define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS) |
| |
| typedef enum { |
| BUS_TYPE_SYSTEM, |
| BUS_TYPE_PCI, |
| BUS_TYPE_SCSI, |
| BUS_TYPE_I2C, |
| BUS_TYPE_SSI |
| } BusType; |
| |
| struct BusState { |
| DeviceState *parent; |
| const char *name; |
| BusType type; |
| QLIST_HEAD(, DeviceState) children; |
| QLIST_ENTRY(BusState) sibling; |
| }; |
| |
| struct Property { |
| const char *name; |
| PropertyInfo *info; |
| int offset; |
| uint8_t bitnr; |
| uint8_t qtype; |
| int64_t defval; |
| int arrayoffset; |
| PropertyInfo *arrayinfo; |
| int arrayfieldsize; |
| }; |
| |
| struct PropertyInfo { |
| const char *name; |
| const char *legacy_name; |
| const char **enum_table; |
| int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); |
| ObjectPropertyAccessor *get; |
| ObjectPropertyAccessor *set; |
| ObjectPropertyRelease *release; |
| }; |
| |
| typedef struct GlobalProperty { |
| const char *driver; |
| const char *property; |
| const char *value; |
| QTAILQ_ENTRY(GlobalProperty) next; |
| } GlobalProperty; |
| |
| /*** Board API. This should go away once we have a machine config file. ***/ |
| |
| DeviceState *qdev_create(BusState *bus, const char *name); |
| DeviceState *qdev_try_create(BusState *bus, const char *name); |
| int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT; |
| void qdev_init_nofail(DeviceState *dev); |
| void qdev_free(DeviceState *dev); |
| |
| /* Set properties between creation and init. */ |
| void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value); |
| void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value); |
| void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); |
| void qdev_set_netdev(DeviceState *dev, NICInfo *nd); |
| |
| qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); |
| void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); |
| |
| BusState *qdev_get_child_bus(DeviceState *dev, const char *name); |
| |
| /*** Device API. ***/ |
| |
| typedef enum { |
| PROP_TYPE_INT, |
| PROP_TYPE_PTR, |
| PROP_TYPE_DEV |
| } DevicePropType; |
| |
| typedef struct { |
| const char *name; |
| DevicePropType type; |
| } DevicePropList; |
| |
| typedef struct DeviceInfo DeviceInfo; |
| |
| typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv, |
| int unit); |
| |
| struct DeviceInfo { |
| const char *name; |
| size_t size; |
| DevicePropList *props; |
| |
| /* Private to qdev / bus. */ |
| qdev_initfn init; |
| BusType bus_type; |
| }; |
| |
| void qdev_register(DeviceInfo *info); |
| |
| // TODO(digit): Remove this. |
| DeviceInfo* qdev_get_device_info(DeviceState *dev); |
| |
| /* Register device properties. */ |
| /* GPIO inputs also double as IRQ sinks. */ |
| void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); |
| void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); |
| |
| CharDriverState *qdev_init_chardev(DeviceState *dev); |
| |
| BusState *qdev_get_parent_bus(DeviceState *dev); |
| uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def); |
| DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name); |
| /* FIXME: Remove opaque pointer properties. */ |
| void *qdev_get_prop_ptr(DeviceState *dev, const char *name); |
| |
| /* Convery from a base type to a parent type, with compile time checking. */ |
| #ifdef __GNUC__ |
| #define DO_UPCAST(type, field, dev) ( __extension__ ( { \ |
| char __attribute__((unused)) offset_must_be_zero[ \ |
| -offsetof(type, field)]; \ |
| container_of(dev, type, field);})) |
| #else |
| #define DO_UPCAST(type, field, dev) container_of(dev, type, field) |
| #endif |
| |
| /*** BUS API. ***/ |
| |
| BusState *qbus_create(BusType type, size_t size, |
| DeviceState *parent, const char *name); |
| |
| #define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev) |
| |
| /*** monitor commands ***/ |
| |
| char *qdev_get_dev_path(DeviceState *dev); |
| |
| #endif // QDEV_CORE_H |