blob: a86fcd0384f728131cdb6a65cecf9497a68350a3 [file] [log] [blame]
#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;
NICInfo *nd;
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