Commit aae9460e244c7abe70b72ff374b3aa102bb09691
1 parent
019d6b8f
Basic qdev infrastructure.
Signed-off-by: Paul Brook <paul@codesourcery.com>
Showing
9 changed files
with
512 additions
and
2 deletions
Makefile
| ... | ... | @@ -101,6 +101,7 @@ OBJS+=bt-hci-csr.o |
| 101 | 101 | OBJS+=buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o |
| 102 | 102 | OBJS+=qemu-char.o aio.o net-checksum.o savevm.o cache-utils.o |
| 103 | 103 | OBJS+=msmouse.o ps2.o |
| 104 | +OBJS+=qdev.o | |
| 104 | 105 | |
| 105 | 106 | ifdef CONFIG_BRLAPI |
| 106 | 107 | OBJS+= baum.o | ... | ... |
Makefile.target
| ... | ... | @@ -486,7 +486,7 @@ endif #CONFIG_BSD_USER |
| 486 | 486 | ifndef CONFIG_USER_ONLY |
| 487 | 487 | |
| 488 | 488 | OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o \ |
| 489 | - gdbstub.o gdbstub-xml.o | |
| 489 | + gdbstub.o gdbstub-xml.o sysbus.o | |
| 490 | 490 | # virtio has to be here due to weird dependency between PCI and virtio-net. |
| 491 | 491 | # need to fix this properly |
| 492 | 492 | OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o | ... | ... |
hw/qdev.c
0 → 100644
| 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, write to the Free Software | |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA | |
| 19 | + */ | |
| 20 | + | |
| 21 | +/* The theory here is that it should be possible to create a machine without | |
| 22 | + knowledge of specific devices. Historically board init routines have | |
| 23 | + passed a bunch of arguments to each device, requiring the board know | |
| 24 | + exactly which device it is dealing with. This file provides an abstract | |
| 25 | + API for device configuration and initialization. Devices will generally | |
| 26 | + inherit from a particular bus (e.g. PCI or I2C) rather than | |
| 27 | + this API directly. */ | |
| 28 | + | |
| 29 | +#include "qdev.h" | |
| 30 | +#include "sysemu.h" | |
| 31 | + | |
| 32 | +struct DeviceProperty { | |
| 33 | + const char *name; | |
| 34 | + union { | |
| 35 | + int i; | |
| 36 | + void *ptr; | |
| 37 | + } value; | |
| 38 | + DeviceProperty *next; | |
| 39 | +}; | |
| 40 | + | |
| 41 | +struct DeviceType { | |
| 42 | + const char *name; | |
| 43 | + qdev_initfn init; | |
| 44 | + void *opaque; | |
| 45 | + int size; | |
| 46 | + DeviceType *next; | |
| 47 | +}; | |
| 48 | + | |
| 49 | +static DeviceType *device_type_list; | |
| 50 | + | |
| 51 | +/* Register a new device type. */ | |
| 52 | +DeviceType *qdev_register(const char *name, int size, qdev_initfn init, | |
| 53 | + void *opaque) | |
| 54 | +{ | |
| 55 | + DeviceType *t; | |
| 56 | + | |
| 57 | + assert(size >= sizeof(DeviceState)); | |
| 58 | + | |
| 59 | + t = qemu_mallocz(sizeof(DeviceType)); | |
| 60 | + t->next = device_type_list; | |
| 61 | + device_type_list = t; | |
| 62 | + t->name = qemu_strdup(name); | |
| 63 | + t->size = size; | |
| 64 | + t->init = init; | |
| 65 | + t->opaque = opaque; | |
| 66 | + | |
| 67 | + return t; | |
| 68 | +} | |
| 69 | + | |
| 70 | +/* Create a new device. This only initializes the device state structure | |
| 71 | + and allows properties to be set. qdev_init should be called to | |
| 72 | + initialize the actual device emulation. */ | |
| 73 | +DeviceState *qdev_create(void *bus, const char *name) | |
| 74 | +{ | |
| 75 | + DeviceType *t; | |
| 76 | + DeviceState *dev; | |
| 77 | + | |
| 78 | + for (t = device_type_list; t; t = t->next) { | |
| 79 | + if (strcmp(t->name, name) == 0) { | |
| 80 | + break; | |
| 81 | + } | |
| 82 | + } | |
| 83 | + if (!t) { | |
| 84 | + fprintf(stderr, "Unknown device '%s'\n", name); | |
| 85 | + exit(1); | |
| 86 | + } | |
| 87 | + | |
| 88 | + dev = qemu_mallocz(t->size); | |
| 89 | + dev->name = name; | |
| 90 | + dev->type = t; | |
| 91 | + dev->bus = bus; | |
| 92 | + return dev; | |
| 93 | +} | |
| 94 | + | |
| 95 | +/* Initialize a device. Device properties should be set before calling | |
| 96 | + this function. IRQs and MMIO regions should be connected/mapped after | |
| 97 | + calling this function. */ | |
| 98 | +void qdev_init(DeviceState *dev) | |
| 99 | +{ | |
| 100 | + dev->type->init(dev, dev->type->opaque); | |
| 101 | +} | |
| 102 | + | |
| 103 | +static DeviceProperty *create_prop(DeviceState *dev, const char *name) | |
| 104 | +{ | |
| 105 | + DeviceProperty *prop; | |
| 106 | + | |
| 107 | + /* TODO: Check for duplicate properties. */ | |
| 108 | + prop = qemu_mallocz(sizeof(*prop)); | |
| 109 | + prop->name = qemu_strdup(name); | |
| 110 | + prop->next = dev->props; | |
| 111 | + dev->props = prop; | |
| 112 | + | |
| 113 | + return prop; | |
| 114 | +} | |
| 115 | + | |
| 116 | +void qdev_set_prop_int(DeviceState *dev, const char *name, int value) | |
| 117 | +{ | |
| 118 | + DeviceProperty *prop; | |
| 119 | + | |
| 120 | + prop = create_prop(dev, name); | |
| 121 | + prop->value.i = value; | |
| 122 | +} | |
| 123 | + | |
| 124 | +void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) | |
| 125 | +{ | |
| 126 | + DeviceProperty *prop; | |
| 127 | + | |
| 128 | + prop = create_prop(dev, name); | |
| 129 | + prop->value.ptr = value; | |
| 130 | +} | |
| 131 | + | |
| 132 | + | |
| 133 | +qemu_irq qdev_get_irq_sink(DeviceState *dev, int n) | |
| 134 | +{ | |
| 135 | + assert(n >= 0 && n < dev->num_irq_sink); | |
| 136 | + return dev->irq_sink[n]; | |
| 137 | +} | |
| 138 | + | |
| 139 | +/* Register device IRQ sinks. */ | |
| 140 | +void qdev_init_irq_sink(DeviceState *dev, qemu_irq_handler handler, int nirq) | |
| 141 | +{ | |
| 142 | + dev->num_irq_sink = nirq; | |
| 143 | + dev->irq_sink = qemu_allocate_irqs(handler, dev, nirq); | |
| 144 | +} | |
| 145 | + | |
| 146 | +/* Get a character (serial) device interface. */ | |
| 147 | +CharDriverState *qdev_init_chardev(DeviceState *dev) | |
| 148 | +{ | |
| 149 | + static int next_serial; | |
| 150 | + static int next_virtconsole; | |
| 151 | + /* FIXME: This is a nasty hack that needs to go away. */ | |
| 152 | + if (strncmp(dev->name, "virtio", 6) == 0) { | |
| 153 | + return virtcon_hds[next_virtconsole++]; | |
| 154 | + } else { | |
| 155 | + return serial_hds[next_serial++]; | |
| 156 | + } | |
| 157 | +} | |
| 158 | + | |
| 159 | +void *qdev_get_bus(DeviceState *dev) | |
| 160 | +{ | |
| 161 | + return dev->bus; | |
| 162 | +} | |
| 163 | + | |
| 164 | +static DeviceProperty *find_prop(DeviceState *dev, const char *name) | |
| 165 | +{ | |
| 166 | + DeviceProperty *prop; | |
| 167 | + | |
| 168 | + for (prop = dev->props; prop; prop = prop->next) { | |
| 169 | + if (strcmp(prop->name, name) == 0) { | |
| 170 | + return prop; | |
| 171 | + } | |
| 172 | + } | |
| 173 | + return NULL; | |
| 174 | +} | |
| 175 | + | |
| 176 | +uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def) | |
| 177 | +{ | |
| 178 | + DeviceProperty *prop; | |
| 179 | + | |
| 180 | + prop = find_prop(dev, name); | |
| 181 | + if (!prop) | |
| 182 | + return def; | |
| 183 | + | |
| 184 | + return prop->value.i; | |
| 185 | +} | |
| 186 | + | |
| 187 | +void *qdev_get_prop_ptr(DeviceState *dev, const char *name) | |
| 188 | +{ | |
| 189 | + DeviceProperty *prop; | |
| 190 | + | |
| 191 | + prop = find_prop(dev, name); | |
| 192 | + assert(prop); | |
| 193 | + return prop->value.ptr; | |
| 194 | +} | |
| 195 | + | |
| 196 | +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) | |
| 197 | +{ | |
| 198 | + assert(dev->num_gpio_in == 0); | |
| 199 | + dev->num_gpio_in = n; | |
| 200 | + dev->gpio_in = qemu_allocate_irqs(handler, dev, n); | |
| 201 | +} | |
| 202 | + | |
| 203 | +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) | |
| 204 | +{ | |
| 205 | + assert(dev->num_gpio_out == 0); | |
| 206 | + dev->num_gpio_out = n; | |
| 207 | + dev->gpio_out = pins; | |
| 208 | +} | |
| 209 | + | |
| 210 | +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) | |
| 211 | +{ | |
| 212 | + assert(n >= 0 && n < dev->num_gpio_in); | |
| 213 | + return dev->gpio_in[n]; | |
| 214 | +} | |
| 215 | + | |
| 216 | +void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) | |
| 217 | +{ | |
| 218 | + assert(n >= 0 && n < dev->num_gpio_out); | |
| 219 | + dev->gpio_out[n] = pin; | |
| 220 | +} | |
| 221 | + | |
| 222 | +static int next_block_unit[IF_COUNT]; | |
| 223 | + | |
| 224 | +/* Get a block device. This should only be used for single-drive devices | |
| 225 | + (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the | |
| 226 | + appropriate bus. */ | |
| 227 | +BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type) | |
| 228 | +{ | |
| 229 | + int unit = next_block_unit[type]++; | |
| 230 | + int index; | |
| 231 | + | |
| 232 | + index = drive_get_index(type, 0, unit); | |
| 233 | + if (index == -1) { | |
| 234 | + return NULL; | |
| 235 | + } | |
| 236 | + return drives_table[index].bdrv; | |
| 237 | +} | ... | ... |
hw/qdev.h
0 → 100644
| 1 | +#ifndef QDEV_H | |
| 2 | +#define QDEV_H | |
| 3 | + | |
| 4 | +#include "hw.h" | |
| 5 | + | |
| 6 | +typedef struct DeviceType DeviceType; | |
| 7 | + | |
| 8 | +typedef struct DeviceProperty DeviceProperty; | |
| 9 | + | |
| 10 | +/* This structure should not be accessed directly. We declare it here | |
| 11 | + so that it can be embedded in individual device state structures. */ | |
| 12 | +struct DeviceState | |
| 13 | +{ | |
| 14 | + const char *name; | |
| 15 | + DeviceType *type; | |
| 16 | + void *bus; | |
| 17 | + DeviceProperty *props; | |
| 18 | + int num_irq_sink; | |
| 19 | + qemu_irq *irq_sink; | |
| 20 | + int num_gpio_out; | |
| 21 | + qemu_irq *gpio_out; | |
| 22 | + int num_gpio_in; | |
| 23 | + qemu_irq *gpio_in; | |
| 24 | +}; | |
| 25 | + | |
| 26 | +/*** Board API. This should go away once we have a machine config file. ***/ | |
| 27 | + | |
| 28 | +DeviceState *qdev_create(void *bus, const char *name); | |
| 29 | +void qdev_init(DeviceState *dev); | |
| 30 | + | |
| 31 | +/* Set properties between creation and init. */ | |
| 32 | +void qdev_set_prop_int(DeviceState *dev, const char *name, int value); | |
| 33 | +void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value); | |
| 34 | + | |
| 35 | +qemu_irq qdev_get_irq_sink(DeviceState *dev, int n); | |
| 36 | +qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); | |
| 37 | +void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); | |
| 38 | + | |
| 39 | +/*** Device API. ***/ | |
| 40 | + | |
| 41 | +typedef void (*qdev_initfn)(DeviceState *dev, void *opaque); | |
| 42 | + | |
| 43 | +DeviceType *qdev_register(const char *name, int size, qdev_initfn init, | |
| 44 | + void *opaque); | |
| 45 | + | |
| 46 | +/* Register device properties. */ | |
| 47 | +void qdev_init_irq_sink(DeviceState *dev, qemu_irq_handler handler, int nirq); | |
| 48 | +void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); | |
| 49 | +void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); | |
| 50 | + | |
| 51 | +CharDriverState *qdev_init_chardev(DeviceState *dev); | |
| 52 | + | |
| 53 | +void *qdev_get_bus(DeviceState *dev); | |
| 54 | +uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def); | |
| 55 | +void *qdev_get_prop_ptr(DeviceState *dev, const char *name); | |
| 56 | + | |
| 57 | +/* Convery from a base type to a parent type, with compile time checking. */ | |
| 58 | +#ifdef __GNUC__ | |
| 59 | +#define DO_UPCAST(type, field, dev) ( __extension__ ( { \ | |
| 60 | + char __attribute__((unused)) offset_must_be_zero[ \ | |
| 61 | + -offsetof(type, field)]; \ | |
| 62 | + container_of(dev, type, field);})) | |
| 63 | +#else | |
| 64 | +#define DO_UPCAST(type, field, dev) container_of(dev, type, field) | |
| 65 | +#endif | |
| 66 | + | |
| 67 | +#endif | ... | ... |
hw/sysbus.c
0 → 100644
| 1 | +/* | |
| 2 | + * System (CPU) Bus device support code | |
| 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, write to the Free Software | |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#include "sysbus.h" | |
| 22 | +#include "sysemu.h" | |
| 23 | + | |
| 24 | +void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) | |
| 25 | +{ | |
| 26 | + assert(n >= 0 && n < dev->num_irq); | |
| 27 | + dev->irqs[n] = 0; | |
| 28 | + if (dev->irqp[n]) { | |
| 29 | + *dev->irqp[n] = irq; | |
| 30 | + } | |
| 31 | +} | |
| 32 | + | |
| 33 | +void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) | |
| 34 | +{ | |
| 35 | + assert(n >= 0 && n < dev->num_mmio); | |
| 36 | + | |
| 37 | + if (dev->mmio[n].addr == addr) { | |
| 38 | + /* ??? region already mapped here. */ | |
| 39 | + return; | |
| 40 | + } | |
| 41 | + if (dev->mmio[n].addr != (target_phys_addr_t)-1) { | |
| 42 | + /* Unregister previous mapping. */ | |
| 43 | + cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size, | |
| 44 | + IO_MEM_UNASSIGNED); | |
| 45 | + } | |
| 46 | + dev->mmio[n].addr = addr; | |
| 47 | + if (dev->mmio[n].cb) { | |
| 48 | + dev->mmio[n].cb(dev, addr); | |
| 49 | + } else { | |
| 50 | + cpu_register_physical_memory(addr, dev->mmio[n].size, | |
| 51 | + dev->mmio[n].iofunc); | |
| 52 | + } | |
| 53 | +} | |
| 54 | + | |
| 55 | + | |
| 56 | +/* Request an IRQ source. The actual IRQ object may be populated later. */ | |
| 57 | +void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) | |
| 58 | +{ | |
| 59 | + int n; | |
| 60 | + | |
| 61 | + assert(dev->num_irq < QDEV_MAX_IRQ); | |
| 62 | + n = dev->num_irq++; | |
| 63 | + dev->irqp[n] = p; | |
| 64 | +} | |
| 65 | + | |
| 66 | +/* Pass IRQs from a target device. */ | |
| 67 | +void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target) | |
| 68 | +{ | |
| 69 | + int i; | |
| 70 | + assert(dev->num_irq == 0); | |
| 71 | + dev->num_irq = target->num_irq; | |
| 72 | + for (i = 0; i < dev->num_irq; i++) { | |
| 73 | + dev->irqp[i] = target->irqp[i]; | |
| 74 | + } | |
| 75 | +} | |
| 76 | + | |
| 77 | +void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc) | |
| 78 | +{ | |
| 79 | + int n; | |
| 80 | + | |
| 81 | + assert(dev->num_mmio < QDEV_MAX_MMIO); | |
| 82 | + n = dev->num_mmio++; | |
| 83 | + dev->mmio[n].addr = -1; | |
| 84 | + dev->mmio[n].size = size; | |
| 85 | + dev->mmio[n].iofunc = iofunc; | |
| 86 | +} | |
| 87 | + | |
| 88 | +void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, | |
| 89 | + mmio_mapfunc cb) | |
| 90 | +{ | |
| 91 | + int n; | |
| 92 | + | |
| 93 | + assert(dev->num_mmio < QDEV_MAX_MMIO); | |
| 94 | + n = dev->num_mmio++; | |
| 95 | + dev->mmio[n].addr = -1; | |
| 96 | + dev->mmio[n].size = size; | |
| 97 | + dev->mmio[n].cb = cb; | |
| 98 | +} | |
| 99 | + | |
| 100 | +static void sysbus_device_init(DeviceState *dev, void *opaque) | |
| 101 | +{ | |
| 102 | + sysbus_initfn init = (sysbus_initfn)opaque; | |
| 103 | + | |
| 104 | + init(sysbus_from_qdev(dev)); | |
| 105 | +} | |
| 106 | + | |
| 107 | +void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) | |
| 108 | +{ | |
| 109 | + assert(size >= sizeof(SysBusDevice)); | |
| 110 | + qdev_register(name, size, sysbus_device_init, init); | |
| 111 | +} | |
| 112 | + | |
| 113 | +DeviceState *sysbus_create_varargs(const char *name, | |
| 114 | + target_phys_addr_t addr, ...) | |
| 115 | +{ | |
| 116 | + DeviceState *dev; | |
| 117 | + SysBusDevice *s; | |
| 118 | + va_list va; | |
| 119 | + qemu_irq irq; | |
| 120 | + int n; | |
| 121 | + | |
| 122 | + dev = qdev_create(NULL, name); | |
| 123 | + s = sysbus_from_qdev(dev); | |
| 124 | + qdev_init(dev); | |
| 125 | + if (addr != (target_phys_addr_t)-1) { | |
| 126 | + sysbus_mmio_map(s, 0, addr); | |
| 127 | + } | |
| 128 | + va_start(va, addr); | |
| 129 | + n = 0; | |
| 130 | + while (1) { | |
| 131 | + irq = va_arg(va, qemu_irq); | |
| 132 | + if (!irq) { | |
| 133 | + break; | |
| 134 | + } | |
| 135 | + sysbus_connect_irq(s, n, irq); | |
| 136 | + n++; | |
| 137 | + } | |
| 138 | + return dev; | |
| 139 | +} | ... | ... |
hw/sysbus.h
0 → 100644
| 1 | +#ifndef HW_SYSBUS_H | |
| 2 | +#define HW_SYSBUS_H 1 | |
| 3 | + | |
| 4 | +/* Devices attached directly to the main system bus. */ | |
| 5 | + | |
| 6 | +#include "qdev.h" | |
| 7 | + | |
| 8 | +#define QDEV_MAX_MMIO 5 | |
| 9 | +#define QDEV_MAX_IRQ 32 | |
| 10 | + | |
| 11 | +typedef struct SysBusDevice SysBusDevice; | |
| 12 | +typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr); | |
| 13 | + | |
| 14 | +struct SysBusDevice { | |
| 15 | + DeviceState qdev; | |
| 16 | + int num_irq; | |
| 17 | + qemu_irq irqs[QDEV_MAX_IRQ]; | |
| 18 | + qemu_irq *irqp[QDEV_MAX_IRQ]; | |
| 19 | + int num_mmio; | |
| 20 | + struct { | |
| 21 | + target_phys_addr_t addr; | |
| 22 | + target_phys_addr_t size; | |
| 23 | + mmio_mapfunc cb; | |
| 24 | + int iofunc; | |
| 25 | + } mmio[QDEV_MAX_MMIO]; | |
| 26 | +}; | |
| 27 | + | |
| 28 | +typedef void (*sysbus_initfn)(SysBusDevice *dev); | |
| 29 | + | |
| 30 | +/* Macros to compensate for lack of type inheritance in C. */ | |
| 31 | +#define sysbus_from_qdev(dev) ((SysBusDevice *)(dev)) | |
| 32 | +#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev) | |
| 33 | + | |
| 34 | +void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init); | |
| 35 | +void *sysbus_new(void); | |
| 36 | +void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, int iofunc); | |
| 37 | +void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, | |
| 38 | + mmio_mapfunc cb); | |
| 39 | +void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); | |
| 40 | +void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); | |
| 41 | + | |
| 42 | + | |
| 43 | +void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq); | |
| 44 | +void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr); | |
| 45 | + | |
| 46 | +/* Legacy helper function for creating devices. */ | |
| 47 | +DeviceState *sysbus_create_varargs(const char *name, | |
| 48 | + target_phys_addr_t addr, ...); | |
| 49 | +static inline DeviceState *sysbus_create_simple(const char *name, | |
| 50 | + target_phys_addr_t addr, | |
| 51 | + qemu_irq irq) | |
| 52 | +{ | |
| 53 | + return sysbus_create_varargs(name, addr, irq, NULL); | |
| 54 | +} | |
| 55 | + | |
| 56 | +#endif /* !HW_SYSBUS_H */ | ... | ... |
qemu-common.h
| ... | ... | @@ -182,6 +182,7 @@ typedef struct PCMCIACardState PCMCIACardState; |
| 182 | 182 | typedef struct MouseTransformInfo MouseTransformInfo; |
| 183 | 183 | typedef struct uWireSlave uWireSlave; |
| 184 | 184 | typedef struct I2SCodec I2SCodec; |
| 185 | +typedef struct DeviceState DeviceState; | |
| 185 | 186 | |
| 186 | 187 | /* CPU save/load. */ |
| 187 | 188 | void cpu_save(QEMUFile *f, void *opaque); | ... | ... |
sysemu.h
| ... | ... | @@ -132,7 +132,8 @@ extern unsigned int nb_prom_envs; |
| 132 | 132 | #endif |
| 133 | 133 | |
| 134 | 134 | typedef enum { |
| 135 | - IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN | |
| 135 | + IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, | |
| 136 | + IF_COUNT | |
| 136 | 137 | } BlockInterfaceType; |
| 137 | 138 | |
| 138 | 139 | typedef enum { |
| ... | ... | @@ -165,6 +166,8 @@ extern void drive_remove(int index); |
| 165 | 166 | extern const char *drive_get_serial(BlockDriverState *bdrv); |
| 166 | 167 | extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv); |
| 167 | 168 | |
| 169 | +BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type); | |
| 170 | + | |
| 168 | 171 | struct drive_opt { |
| 169 | 172 | const char *file; |
| 170 | 173 | char opt[1024]; |
| ... | ... | @@ -259,4 +262,6 @@ int get_param_value(char *buf, int buf_size, |
| 259 | 262 | const char *tag, const char *str); |
| 260 | 263 | int check_params(const char * const *params, const char *str); |
| 261 | 264 | |
| 265 | +void register_devices(void); | |
| 266 | + | |
| 262 | 267 | #endif | ... | ... |
vl.c
| ... | ... | @@ -2565,6 +2565,8 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) |
| 2565 | 2565 | case IF_MTD: |
| 2566 | 2566 | case IF_VIRTIO: |
| 2567 | 2567 | break; |
| 2568 | + case IF_COUNT: | |
| 2569 | + abort(); | |
| 2568 | 2570 | } |
| 2569 | 2571 | if (!file[0]) |
| 2570 | 2572 | return -2; |
| ... | ... | @@ -5896,6 +5898,8 @@ int main(int argc, char **argv, char **envp) |
| 5896 | 5898 | } |
| 5897 | 5899 | } |
| 5898 | 5900 | |
| 5901 | + module_call_init(MODULE_INIT_DEVICE); | |
| 5902 | + | |
| 5899 | 5903 | machine->init(ram_size, boot_devices, |
| 5900 | 5904 | kernel_filename, kernel_cmdline, initrd_filename, cpu_model); |
| 5901 | 5905 | ... | ... |