Basic qdev infrastructure.
Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
parent
019d6b8ff0
commit
aae9460e24
1
Makefile
1
Makefile
|
@ -101,6 +101,7 @@ OBJS+=bt-hci-csr.o
|
||||||
OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
|
OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
|
||||||
OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
|
OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o
|
||||||
OBJS+=msmouse.o ps2.o
|
OBJS+=msmouse.o ps2.o
|
||||||
|
OBJS+=qdev.o
|
||||||
|
|
||||||
ifdef CONFIG_BRLAPI
|
ifdef CONFIG_BRLAPI
|
||||||
OBJS+= baum.o
|
OBJS+= baum.o
|
||||||
|
|
|
@ -486,7 +486,7 @@ endif #CONFIG_BSD_USER
|
||||||
ifndef CONFIG_USER_ONLY
|
ifndef CONFIG_USER_ONLY
|
||||||
|
|
||||||
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \
|
OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \
|
||||||
gdbstub.o gdbstub-xml.o
|
gdbstub.o gdbstub-xml.o sysbus.o
|
||||||
# virtio has to be here due to weird dependency between PCI and virtio-net.
|
# virtio has to be here due to weird dependency between PCI and virtio-net.
|
||||||
# need to fix this properly
|
# need to fix this properly
|
||||||
OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
|
OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
* Dynamic device configuration and creation.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 CodeSourcery
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The theory here is that it should be possible to create a machine without
|
||||||
|
knowledge of specific devices. Historically board init routines have
|
||||||
|
passed a bunch of arguments to each device, requiring the board know
|
||||||
|
exactly which device it is dealing with. This file provides an abstract
|
||||||
|
API for device configuration and initialization. Devices will generally
|
||||||
|
inherit from a particular bus (e.g. PCI or I2C) rather than
|
||||||
|
this API directly. */
|
||||||
|
|
||||||
|
#include "qdev.h"
|
||||||
|
#include "sysemu.h"
|
||||||
|
|
||||||
|
struct DeviceProperty {
|
||||||
|
const char *name;
|
||||||
|
union {
|
||||||
|
int i;
|
||||||
|
void *ptr;
|
||||||
|
} value;
|
||||||
|
DeviceProperty *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DeviceType {
|
||||||
|
const char *name;
|
||||||
|
qdev_initfn init;
|
||||||
|
void *opaque;
|
||||||
|
int size;
|
||||||
|
DeviceType *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DeviceType *device_type_list;
|
||||||
|
|
||||||
|
/* Register a new device type. */
|
||||||
|
DeviceType *qdev_register(const char *name, int size, qdev_initfn init,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
DeviceType *t;
|
||||||
|
|
||||||
|
assert(size >= sizeof(DeviceState));
|
||||||
|
|
||||||
|
t = qemu_mallocz(sizeof(DeviceType));
|
||||||
|
t->next = device_type_list;
|
||||||
|
device_type_list = t;
|
||||||
|
t->name = qemu_strdup(name);
|
||||||
|
t->size = size;
|
||||||
|
t->init = init;
|
||||||
|
t->opaque = opaque;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new device. This only initializes the device state structure
|
||||||
|
and allows properties to be set. qdev_init should be called to
|
||||||
|
initialize the actual device emulation. */
|
||||||
|
DeviceState *qdev_create(void *bus, const char *name)
|
||||||
|
{
|
||||||
|
DeviceType *t;
|
||||||
|
DeviceState *dev;
|
||||||
|
|
||||||
|
for (t = device_type_list; t; t = t->next) {
|
||||||
|
if (strcmp(t->name, name) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!t) {
|
||||||
|
fprintf(stderr, "Unknown device '%s'\n", name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = qemu_mallocz(t->size);
|
||||||
|
dev->name = name;
|
||||||
|
dev->type = t;
|
||||||
|
dev->bus = bus;
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize a device. Device properties should be set before calling
|
||||||
|
this function. IRQs and MMIO regions should be connected/mapped after
|
||||||
|
calling this function. */
|
||||||
|
void qdev_init(DeviceState *dev)
|
||||||
|
{
|
||||||
|
dev->type->init(dev, dev->type->opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeviceProperty *create_prop(DeviceState *dev, const char *name)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
/* TODO: Check for duplicate properties. */
|
||||||
|
prop = qemu_mallocz(sizeof(*prop));
|
||||||
|
prop->name = qemu_strdup(name);
|
||||||
|
prop->next = dev->props;
|
||||||
|
dev->props = prop;
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_set_prop_int(DeviceState *dev, const char *name, int value)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
prop = create_prop(dev, name);
|
||||||
|
prop->value.i = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
prop = create_prop(dev, name);
|
||||||
|
prop->value.ptr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qemu_irq qdev_get_irq_sink(DeviceState *dev, int n)
|
||||||
|
{
|
||||||
|
assert(n >= 0 && n < dev->num_irq_sink);
|
||||||
|
return dev->irq_sink[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register device IRQ sinks. */
|
||||||
|
void qdev_init_irq_sink(DeviceState *dev, qemu_irq_handler handler, int nirq)
|
||||||
|
{
|
||||||
|
dev->num_irq_sink = nirq;
|
||||||
|
dev->irq_sink = qemu_allocate_irqs(handler, dev, nirq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a character (serial) device interface. */
|
||||||
|
CharDriverState *qdev_init_chardev(DeviceState *dev)
|
||||||
|
{
|
||||||
|
static int next_serial;
|
||||||
|
static int next_virtconsole;
|
||||||
|
/* FIXME: This is a nasty hack that needs to go away. */
|
||||||
|
if (strncmp(dev->name, "virtio", 6) == 0) {
|
||||||
|
return virtcon_hds[next_virtconsole++];
|
||||||
|
} else {
|
||||||
|
return serial_hds[next_serial++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *qdev_get_bus(DeviceState *dev)
|
||||||
|
{
|
||||||
|
return dev->bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeviceProperty *find_prop(DeviceState *dev, const char *name)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
for (prop = dev->props; prop; prop = prop->next) {
|
||||||
|
if (strcmp(prop->name, name) == 0) {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
prop = find_prop(dev, name);
|
||||||
|
if (!prop)
|
||||||
|
return def;
|
||||||
|
|
||||||
|
return prop->value.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
|
||||||
|
{
|
||||||
|
DeviceProperty *prop;
|
||||||
|
|
||||||
|
prop = find_prop(dev, name);
|
||||||
|
assert(prop);
|
||||||
|
return prop->value.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||||
|
{
|
||||||
|
assert(dev->num_gpio_in == 0);
|
||||||
|
dev->num_gpio_in = n;
|
||||||
|
dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
|
||||||
|
{
|
||||||
|
assert(dev->num_gpio_out == 0);
|
||||||
|
dev->num_gpio_out = n;
|
||||||
|
dev->gpio_out = pins;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
|
||||||
|
{
|
||||||
|
assert(n >= 0 && n < dev->num_gpio_in);
|
||||||
|
return dev->gpio_in[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
|
||||||
|
{
|
||||||
|
assert(n >= 0 && n < dev->num_gpio_out);
|
||||||
|
dev->gpio_out[n] = pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int next_block_unit[IF_COUNT];
|
||||||
|
|
||||||
|
/* Get a block device. This should only be used for single-drive devices
|
||||||
|
(e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
|
||||||
|
appropriate bus. */
|
||||||
|
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
|
||||||
|
{
|
||||||
|
int unit = next_block_unit[type]++;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
index = drive_get_index(type, 0, unit);
|
||||||
|
if (index == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return drives_table[index].bdrv;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef QDEV_H
|
||||||
|
#define QDEV_H
|
||||||
|
|
||||||
|
#include "hw.h"
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
DeviceType *type;
|
||||||
|
void *bus;
|
||||||
|
DeviceProperty *props;
|
||||||
|
int num_irq_sink;
|
||||||
|
qemu_irq *irq_sink;
|
||||||
|
int num_gpio_out;
|
||||||
|
qemu_irq *gpio_out;
|
||||||
|
int num_gpio_in;
|
||||||
|
qemu_irq *gpio_in;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** Board API. This should go away once we have a machine config file. ***/
|
||||||
|
|
||||||
|
DeviceState *qdev_create(void *bus, const char *name);
|
||||||
|
void qdev_init(DeviceState *dev);
|
||||||
|
|
||||||
|
/* Set properties between creation and init. */
|
||||||
|
void qdev_set_prop_int(DeviceState *dev, const char *name, int value);
|
||||||
|
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value);
|
||||||
|
|
||||||
|
qemu_irq qdev_get_irq_sink(DeviceState *dev, int n);
|
||||||
|
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
|
||||||
|
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
|
||||||
|
|
||||||
|
/*** Device API. ***/
|
||||||
|
|
||||||
|
typedef void (*qdev_initfn)(DeviceState *dev, void *opaque);
|
||||||
|
|
||||||
|
DeviceType *qdev_register(const char *name, int size, qdev_initfn init,
|
||||||
|
void *opaque);
|
||||||
|
|
||||||
|
/* Register device properties. */
|
||||||
|
void qdev_init_irq_sink(DeviceState *dev, qemu_irq_handler handler, int nirq);
|
||||||
|
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);
|
||||||
|
|
||||||
|
void *qdev_get_bus(DeviceState *dev);
|
||||||
|
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def);
|
||||||
|
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
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* System (CPU) Bus device support code
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 CodeSourcery
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sysbus.h"
|
||||||
|
#include "sysemu.h"
|
||||||
|
|
||||||
|
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
||||||
|
{
|
||||||
|
assert(n >= 0 && n < dev->num_irq);
|
||||||
|
dev->irqs[n] = 0;
|
||||||
|
if (dev->irqp[n]) {
|
||||||
|
*dev->irqp[n] = irq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
|
||||||
|
{
|
||||||
|
assert(n >= 0 && n < dev->num_mmio);
|
||||||
|
|
||||||
|
if (dev->mmio[n].addr == addr) {
|
||||||
|
/* ??? region already mapped here. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
|
||||||
|
/* Unregister previous mapping. */
|
||||||
|
cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
|
||||||
|
IO_MEM_UNASSIGNED);
|
||||||
|
}
|
||||||
|
dev->mmio[n].addr = addr;
|
||||||
|
if (dev->mmio[n].cb) {
|
||||||
|
dev->mmio[n].cb(dev, addr);
|
||||||
|
} else {
|
||||||
|
cpu_register_physical_memory(addr, dev->mmio[n].size,
|
||||||
|
dev->mmio[n].iofunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Request an IRQ source. The actual IRQ object may be populated later. */
|
||||||
|
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
assert(dev->num_irq < QDEV_MAX_IRQ);
|
||||||
|
n = dev->num_irq++;
|
||||||
|
dev->irqp[n] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass IRQs from a target device. */
|
||||||
|
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
assert(dev->num_irq == 0);
|
||||||
|
dev->num_irq = target->num_irq;
|
||||||
|
for (i = 0; i < dev->num_irq; i++) {
|
||||||
|
dev->irqp[i] = target->irqp[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
assert(dev->num_mmio < QDEV_MAX_MMIO);
|
||||||
|
n = dev->num_mmio++;
|
||||||
|
dev->mmio[n].addr = -1;
|
||||||
|
dev->mmio[n].size = size;
|
||||||
|
dev->mmio[n].iofunc = iofunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
|
||||||
|
mmio_mapfunc cb)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
assert(dev->num_mmio < QDEV_MAX_MMIO);
|
||||||
|
n = dev->num_mmio++;
|
||||||
|
dev->mmio[n].addr = -1;
|
||||||
|
dev->mmio[n].size = size;
|
||||||
|
dev->mmio[n].cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sysbus_device_init(DeviceState *dev, void *opaque)
|
||||||
|
{
|
||||||
|
sysbus_initfn init = (sysbus_initfn)opaque;
|
||||||
|
|
||||||
|
init(sysbus_from_qdev(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init)
|
||||||
|
{
|
||||||
|
assert(size >= sizeof(SysBusDevice));
|
||||||
|
qdev_register(name, size, sysbus_device_init, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceState *sysbus_create_varargs(const char *name,
|
||||||
|
target_phys_addr_t addr, ...)
|
||||||
|
{
|
||||||
|
DeviceState *dev;
|
||||||
|
SysBusDevice *s;
|
||||||
|
va_list va;
|
||||||
|
qemu_irq irq;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
dev = qdev_create(NULL, name);
|
||||||
|
s = sysbus_from_qdev(dev);
|
||||||
|
qdev_init(dev);
|
||||||
|
if (addr != (target_phys_addr_t)-1) {
|
||||||
|
sysbus_mmio_map(s, 0, addr);
|
||||||
|
}
|
||||||
|
va_start(va, addr);
|
||||||
|
n = 0;
|
||||||
|
while (1) {
|
||||||
|
irq = va_arg(va, qemu_irq);
|
||||||
|
if (!irq) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sysbus_connect_irq(s, n, irq);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return dev;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef HW_SYSBUS_H
|
||||||
|
#define HW_SYSBUS_H 1
|
||||||
|
|
||||||
|
/* Devices attached directly to the main system bus. */
|
||||||
|
|
||||||
|
#include "qdev.h"
|
||||||
|
|
||||||
|
#define QDEV_MAX_MMIO 5
|
||||||
|
#define QDEV_MAX_IRQ 32
|
||||||
|
|
||||||
|
typedef struct SysBusDevice SysBusDevice;
|
||||||
|
typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr);
|
||||||
|
|
||||||
|
struct SysBusDevice {
|
||||||
|
DeviceState qdev;
|
||||||
|
int num_irq;
|
||||||
|
qemu_irq irqs[QDEV_MAX_IRQ];
|
||||||
|
qemu_irq *irqp[QDEV_MAX_IRQ];
|
||||||
|
int num_mmio;
|
||||||
|
struct {
|
||||||
|
target_phys_addr_t addr;
|
||||||
|
target_phys_addr_t size;
|
||||||
|
mmio_mapfunc cb;
|
||||||
|
int iofunc;
|
||||||
|
} mmio[QDEV_MAX_MMIO];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*sysbus_initfn)(SysBusDevice *dev);
|
||||||
|
|
||||||
|
/* Macros to compensate for lack of type inheritance in C. */
|
||||||
|
#define sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
|
||||||
|
#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev)
|
||||||
|
|
||||||
|
void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);
|
||||||
|
void *sysbus_new(void);
|
||||||
|
void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc);
|
||||||
|
void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
|
||||||
|
mmio_mapfunc cb);
|
||||||
|
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
|
||||||
|
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
|
||||||
|
|
||||||
|
|
||||||
|
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
|
||||||
|
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr);
|
||||||
|
|
||||||
|
/* Legacy helper function for creating devices. */
|
||||||
|
DeviceState *sysbus_create_varargs(const char *name,
|
||||||
|
target_phys_addr_t addr, ...);
|
||||||
|
static inline DeviceState *sysbus_create_simple(const char *name,
|
||||||
|
target_phys_addr_t addr,
|
||||||
|
qemu_irq irq)
|
||||||
|
{
|
||||||
|
return sysbus_create_varargs(name, addr, irq, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !HW_SYSBUS_H */
|
|
@ -182,6 +182,7 @@ typedef struct PCMCIACardState PCMCIACardState;
|
||||||
typedef struct MouseTransformInfo MouseTransformInfo;
|
typedef struct MouseTransformInfo MouseTransformInfo;
|
||||||
typedef struct uWireSlave uWireSlave;
|
typedef struct uWireSlave uWireSlave;
|
||||||
typedef struct I2SCodec I2SCodec;
|
typedef struct I2SCodec I2SCodec;
|
||||||
|
typedef struct DeviceState DeviceState;
|
||||||
|
|
||||||
/* CPU save/load. */
|
/* CPU save/load. */
|
||||||
void cpu_save(QEMUFile *f, void *opaque);
|
void cpu_save(QEMUFile *f, void *opaque);
|
||||||
|
|
7
sysemu.h
7
sysemu.h
|
@ -132,7 +132,8 @@ extern unsigned int nb_prom_envs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN
|
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
|
||||||
|
IF_COUNT
|
||||||
} BlockInterfaceType;
|
} BlockInterfaceType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -165,6 +166,8 @@ extern void drive_remove(int index);
|
||||||
extern const char *drive_get_serial(BlockDriverState *bdrv);
|
extern const char *drive_get_serial(BlockDriverState *bdrv);
|
||||||
extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv);
|
extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv);
|
||||||
|
|
||||||
|
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
|
||||||
|
|
||||||
struct drive_opt {
|
struct drive_opt {
|
||||||
const char *file;
|
const char *file;
|
||||||
char opt[1024];
|
char opt[1024];
|
||||||
|
@ -259,4 +262,6 @@ int get_param_value(char *buf, int buf_size,
|
||||||
const char *tag, const char *str);
|
const char *tag, const char *str);
|
||||||
int check_params(const char * const *params, const char *str);
|
int check_params(const char * const *params, const char *str);
|
||||||
|
|
||||||
|
void register_devices(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
4
vl.c
4
vl.c
|
@ -2565,6 +2565,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
|
||||||
case IF_MTD:
|
case IF_MTD:
|
||||||
case IF_VIRTIO:
|
case IF_VIRTIO:
|
||||||
break;
|
break;
|
||||||
|
case IF_COUNT:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
if (!file[0])
|
if (!file[0])
|
||||||
return -2;
|
return -2;
|
||||||
|
@ -5896,6 +5898,8 @@ int main(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_DEVICE);
|
||||||
|
|
||||||
machine->init(ram_size, boot_devices,
|
machine->init(ram_size, boot_devices,
|
||||||
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
||||||
|
|
||||||
|
|
Reference in New Issue