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 | ... | ... |