blob: 49ed713485034e7f5de97c844b569e6ece6baec1 [file] [log] [blame]
DeviceState/SysBus in master/qemu:
===========================================================================
Defined in <hw/qdev-core.h>
Typical sequence to create a new DeviceState instance:
DeviceState* dev = qdev_create(parent_bus, device_class_name);
qdev_set_prop_int(dev, "<property-name>", value);
... // set other properties.
qdev_init(dev); // real initialization / realization here.
return dev;
Registering a new DeviceState class (a.k.a. DeviceInfo):
DeviceInfo info = g_malloc0(sizeof(*info));
info->name = DEVICE_CLASS_NAME;
info->size = sizeof(MyDeviceState);
info->init = my_device_state_init;
info->bus_type = DEVICE_BUS_TYPE; // SYSTEM / PCI / LSI / etc.
qdev_register(&info);
DeviceState has:
type : *DeviceType -> should really be DeviceInfo, see below.
parent_bus: *BusState -> parent bus the device is attached to.
props: *DeviceProperty -> WHAT ARE THESE ???
num_gpio_out: int -> number of output IRQ pins.
gpio_out: *qemu_irq -> array of output IRQ pins.
num_gpio_in: int -> number of input IRQ pins.
gpio_in: *qemu_irq -> array of input IRQ pins.
child_bus: QLIST_HEAD(, BusState) -> optional child bus provided by device?
nd: *NICInfo ?? -> WHAT IS THIS ???
sibling: QLIST_ENTRY(DeviceState) -> next device attached to same |parent_bus|.
BusState has:
parent: *DeviceState -> parent device, if any?
name: *char -> bus name. What is used for?
type: BusType -> SYSTEM, PCI, SCSI, I2C or SSI. Why?
DeviceInfo: -> Really a device class descriptor.
name: *const char -> Name of device class.
size: size_t -> Size of device instance, must be >= sizeof(DeviceState).
props: *DevicePropList ->
init: qdev_initfn
bus_type: BusType.
DeviceType: -> Defined and used by hw/core/qdev.c to to maintain the list of
registered DeviceInfo values (added by calling qdev_register()).
info: *DeviceInfo -> device class descriptor.
next: *DeviceType -> next item in list.
DeviceProperty:
name: *const_char -> property name.
type: DevicePropertyType -> INT, PTR or DEV ???
value: union{uint64_t, void*} -> property value.
DevicePropList: Individual array item describing a device property.
Used in DeviceInfo to list which properties a given DeviceState
supports.
name: *const_char -> property name.
type: DevicePropertyType -> INT, PTR or DEV ?
// Create a new, totally empty, DeviceState instance.
// |bus| is the parent bus instance, if NULL, this indicates that the device
// will be attached to the main system bus (created internally on demand by
// this function).
// |name| is the device class name, i.e. must match the |name| field of a
// registered DeviceInfo.
// Return a new DeviceState instance on success, panic on failure.
//
// IMPORTANT: The DeviceState is allocated with g_malloc0() but is not
// initialized when the function returns!! It is just added
// to the parent bus' list.
//
// Possible failure modes:
// - |name| doesn't match a registered DeviceInfo.
// - The |bus_type| field of the DeviceInfo does not match the one of
// the parent |bus|.
DeviceState* qdev_create(BusState* bus, const char* name);
// Initialize a given DeviceState. Assumes that all device properties were
// set before calling this function, and that IRQs and MMIO regions are also
// already connected. This simply calls the |init| function of the device's
// DeviceInfo class descriptor.
void qdev_init(DeviceState* dev);
// Unlink a device from a bus and free the structure. NOTE: This does not
// perform any de-initialization.
qdev_free(DeviceState* dev);
// Sets a device property to a given integer value.
// |dev| is the target DeviceState that holds the property value.
// |name| is the property name.
// |value| is the 64-bit value.
// NOTE: This function doesn't check that the property name actually
// matches any of the properties listed in the DeviceInfo, or
// that their type matches. It also doesn't check for any
// previously existing with the same name, it just prepends
// to the list.
void qdev_set_prop(DeviceState* dev, const char* name, uint64_t value);
// Same a qdev_set_prop() for property values of type DEV
void qdev_set_prop_dev(DeviceState* dev, const char* name DeviceState* value);
// Same a qdev_set_prop() for property values of type PTR
void qdev_set_prop_ptr(DeviceState* dev, const char* name, void* value);
// Find if the device |dev| has a value for property |name|, and return it
// if it does, otherwise return |def|. This assert()s that the property
// type is an integer (INT).
uint64_t qdev_get_prop_int(DeviceState* dev, const char* name, uint64_t def);
// Find if the device |dev| has a pointer value for property |name|, and
// return it if it does. Otherwise, assert(NULL). NOTE THE UNEXPECTED ASSERT
// HERE!
void* qdev_get_prop_ptr(DeviceState* dev, const char* name);
// Find if the device |dev| has a DeviceState value for property |name|,
// and return it if it does, or NULL if it doesn't.
DeviceState* qdev_get_prop_dev(DeviceState* dev, const char* name);
// Despite its name, this doesn't do any kind of initialization, this just
// returns a new CharDriverState which was previously added to the global
// |serial_hds| or |virtcon_hds| arrays. Which one is selected depends
// on the device's DeviceInfo |name| field. If it starts with 'virtio'
// then it comes from |virtcon_hds|, otherwise from |serial_hds|.
// There is a FIXME here to 'get rid of this hack'.
CharDriveState* qdev_init_chardev(DeviceState* dev);
// Just return device's |parent_bus| field falue.
BusState* qdev_get_parent_bus(DeviceState* dev);
// Allocate |n| input IRQ pins that all will be handled by the |handler|
// callback for device |dev|.
void qdev_init_gpio_in(DeviceState* dev, qemu_irq_handler handler, int n);
// Allocate |n| output IRQ pins that all will be handled by the |handler|
// callback for device |dev|.
void qdev_init_gpio_out(DeviceState* dev, qemu_irq_handler handler, int n);
// Return IRQ pin indexed by |n| for device |dev|.
// The value of |n| must be between 0 (included) and the value passed
// to qdev_init_qpio_in() (excluded).
qemu_irq qdev_get_gpio_in(DeviceState* dev, int n);
// Guess what.
qemu_irq qdev_get_gpio_out(DeviceState* dev, int n);
// Set the |nd| field of a given DeviceState. Looks like it's network related.
void qdev_set_netdev(DeviceState* dev, NICInfo* nd);
// Create a new VLANClientState instance using the device's |nd| field
// to extract the vlan, model and name to call qemu_new_vlan_client().
// assert that qdev_set_netdev() was called previously on the device.
// WHY???
VLANClientState* qdev_get_vlan_client(DeviceState *dev,
NetCanReceive* can_receive,
NetReceive* receive,
NetReceiveIOV* receive_iov,
NetCleanup* cleanup,
void* opaque);
// Return |dev|'s MAC address into |*macaddr| (6 bytes), extracting it from
// the device's netdev |nd| field.
void qdev_get_macaddr(DeviceState* dev, uint8_t* macaddr);
// UNUSED AND PROBABLY MISPLACED, since it completely ignores |dev|.
// Used to get the BlockDriverState instance of a given block interface |type|.
// This calls drive_get(type, 0, unit), where |unit| is computed internally
// by a static type-specific counter.
BlockDriverState* qdev_init_bdrv(DeviceState* dev, BlockInterfaceType type);
// Return a device's child bus of a given name, or NULL.
// |dev| is the device that may provide its own buses.
// |name| is the name of the child bus to match.
BusState* qdev_get_child_bus(DeviceState* state, const char* name);
// Create new bus instance.
// |type| is the bus type (SYSTEM, PCI, SCSI, I2C, SSI)
// |size| is the instance size, must be >= sizeof(BusState).
// |parent| is the parent bbus, can be NULL.
// |name| is the bus' name.
BusState* qbus_create(BusType type,
size_t size,
DeviceState* parent,
const char* name);
// Supposed to return a string describing the device's path from the
// main system bus. Currently unimplemented, always return NULL!
char* qdev_get_dev_path(DeviceState* dev);
SysBusDevice:
qdev: DeviceState -> base DeviceState members.
num_irq: int -> number of IRQs used by bus?
irqs: qemu_irq[32] -> array of pointers to IRQ pins.
irqp: (*qemu_irq)[32] -> array of pointers to pointers to IRQ pins? WHAT???
num_mmio: int -> number of MMIO regions.
mmio: struct{}[5] -> array of MMIO region descriptor.
Each mmio region has:
addr: hwaddr
size: hwaddr
cb: mmio_mapfunc cb -> function used to map I/O memory.
iofunc: int
SysBusDeviceInfo:
qdev: DeviceInfo -> base DeviceInfo class descriptor.
init: sysbuf_initfn -> bus initialization function. ???
// Register a new SysBusDevice class. This creates a new SysBusDeviceInfo
// instance recording the name, size and initialization function corresponding
// to a class of SysBufDevice instances.
// |name| is the DeviceInfo class name.
// |size| is the instance size, must be >= sizeof(SysBusDevice)
// |init| if the sysbus_initfn for instances of this class.
sysbus_register_dev(const char* name, size_t size, sysbus_initfn init);
// Used internally to set the parent DeviceInfo |bus_type| and |init|.
// before calling qdev_register() to register the system bus device class.
sysbus_register_withprop(SysBusDeviceInfo* info);
// Allocate but do not map a new MMIO region of |size| bytes, using
// the |iofunc| MMIO function index.
// |dev| points to an existing SysBusDevice.
// NOTE: The region can later be mapped by calling sysbus_mmio_map.
void sysbus_init_mmio(SysBusDevice* dev, hwaddr size, int iofunc);
// REMOVED: Allocate but do not map a new MMIO region of |size| byutes, using
// a custom |cb| mapping callback.
// |dev| points to an existing SysBusDevice.
// NOTE: The region can later be mapped by calling sysbus_mmio_map.
void sysbus_init_mmio_cb(SysBusDevice* dev, hwaddr size, mmio_mapfunc cb);
// Map a system bus device MMIO region, identified by index |n|, at address
// |addr|. The index correspond to the sequence of previous calls to
// sysbus_init_mmio() or sysbus_init_mmio_cb(). First call creates index 0.
// NOTE: It's possible to call this multiple time to remap the region to
// a different address.
void sysbus_mmio_map(SysBusDevice* dev, int n, hwaddr addr);
// Allocate an IRQ source. The function takes the address of a qemu_irq
// value that can be populated/set later, by calling sysbus_connect_irq.
// In other words, this function records the pointer in an array for later
// user.
sysbus_init_irq(SysBusDevice* dev, qemu_irq* p);
// Connect an IRQ source to the actual device. |n| is an index corresponding
// to the sequence of previous calls to sysbus_init_irq(), and |irq| is the
// IRQ to use as the source. This function really writes |irq| to the pointer
// that was previously registered with sysbus_init_irq(), and nothing more.
sysbus_connect_irq(SysBusDevice* dev, int n, qemu_irq irq);
// Pass all
sysbus_pass_irq(SysBusDevice* dev, SysBusDevice* target);
PCIDevice:
qdev: DeviceState -> base DeviceState fields.
config: uint8_t[256] -> PCI config space?
bus: *PCIBus -> PCI Bus instance this device belongs to.
devfn: int -> PCI device function index
name: char[64]
io_regions: PCIIORegion[PCI_NUM_REGIONS]
config_read: *PCIConfigReadFunc
config_write: *PCIConfigWriteFunc
unregister: *PCIUnregisterFunc
irq: *qemu_irq -> IRQ objects for the INTA-INTD pins ???
irq_state: int[4] -> current IRQ levels. ???
PCIIORegion:
addr: uint32_t -> PCI mapping address, -1 means not mapped.
size: uint32_t
type: uint8_t
map_func: *PCIMapIORegioFunc
PCIBus:
qbus: BusState -> base BusState fields.
bus_num: int -> ?
devfn_min: int -> ?
set_irq: pci_set_irq_fn
map_irq: pci_map_irq_fn
config_reg: uint32_t -> UNUSED
low_set_irq: qemu_irq_handler
irq_opaque: qemu_irq
devices: (*PCIDevice)[256]
parent_dev: *PCIDevice
next: *PCIBus
nirq: int
irq_count: int[]